| author | wenzelm | 
| Wed, 29 Nov 2023 00:07:54 +0100 | |
| changeset 79074 | 7f24c5be57bd | 
| parent 79020 | ef76705bf402 | 
| permissions | -rw-r--r-- | 
| 77238 | 1  | 
/* Title: Pure/Tools/build_process.scala  | 
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  | 
||
| 77505 | 11  | 
import scala.collection.immutable.SortedMap  | 
| 77246 | 12  | 
import scala.math.Ordering  | 
| 77257 | 13  | 
import scala.annotation.tailrec  | 
| 77246 | 14  | 
|
15  | 
||
| 77238 | 16  | 
object Build_Process {
 | 
| 78421 | 17  | 
/** state vs. database **/  | 
| 77257 | 18  | 
|
| 78238 | 19  | 
sealed case class Build(  | 
| 78173 | 20  | 
build_uuid: String, // Database_Progress.context_uuid  | 
| 77660 | 21  | 
ml_platform: String,  | 
22  | 
options: String,  | 
|
23  | 
start: Date,  | 
|
| 78226 | 24  | 
stop: Option[Date],  | 
25  | 
sessions: List[String]  | 
|
| 78222 | 26  | 
  ) {
 | 
27  | 
def active: Boolean = stop.isEmpty  | 
|
| 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  | 
||
| 78238 | 43  | 
sealed case class Task(  | 
| 77631 | 44  | 
name: String,  | 
45  | 
deps: List[String],  | 
|
| 
77661
 
45bd5c26cbcc
proper build_uuid for Build_Process.Task: thus old entries are removed via prepare_database/clean_build;
 
wenzelm 
parents: 
77660 
diff
changeset
 | 
46  | 
info: JSON.Object.T,  | 
| 
 
45bd5c26cbcc
proper build_uuid for Build_Process.Task: thus old entries are removed via prepare_database/clean_build;
 
wenzelm 
parents: 
77660 
diff
changeset
 | 
47  | 
build_uuid: String  | 
| 77631 | 48  | 
  ) {
 | 
| 
77313
 
f8aa1647d156
more elementary data structures, to fit better to SQL database;
 
wenzelm 
parents: 
77312 
diff
changeset
 | 
49  | 
def is_ready: Boolean = deps.isEmpty  | 
| 77585 | 50  | 
def resolve(dep: String): Task =  | 
| 
77313
 
f8aa1647d156
more elementary data structures, to fit better to SQL database;
 
wenzelm 
parents: 
77312 
diff
changeset
 | 
51  | 
if (deps.contains(dep)) copy(deps = deps.filterNot(_ == dep)) else this  | 
| 
 
f8aa1647d156
more elementary data structures, to fit better to SQL database;
 
wenzelm 
parents: 
77312 
diff
changeset
 | 
52  | 
}  | 
| 
 
f8aa1647d156
more elementary data structures, to fit better to SQL database;
 
wenzelm 
parents: 
77312 
diff
changeset
 | 
53  | 
|
| 78238 | 54  | 
sealed case class Job(  | 
| 
77630
 
86ef80d13544
clarified signature: avoid confusion due to object-orientation;
 
wenzelm 
parents: 
77629 
diff
changeset
 | 
55  | 
name: String,  | 
| 
 
86ef80d13544
clarified signature: avoid confusion due to object-orientation;
 
wenzelm 
parents: 
77629 
diff
changeset
 | 
56  | 
worker_uuid: String,  | 
| 77634 | 57  | 
build_uuid: String,  | 
| 
77630
 
86ef80d13544
clarified signature: avoid confusion due to object-orientation;
 
wenzelm 
parents: 
77629 
diff
changeset
 | 
58  | 
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: 
78839 
diff
changeset
 | 
59  | 
start_date: Date,  | 
| 
77630
 
86ef80d13544
clarified signature: avoid confusion due to object-orientation;
 
wenzelm 
parents: 
77629 
diff
changeset
 | 
60  | 
build: Option[Build_Job]  | 
| 
77652
 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 
wenzelm 
parents: 
77651 
diff
changeset
 | 
61  | 
  ) extends Library.Named {
 | 
| 78530 | 62  | 
def join_build: Option[Build_Job.Result] = build.flatMap(_.join)  | 
| 
77630
 
86ef80d13544
clarified signature: avoid confusion due to object-orientation;
 
wenzelm 
parents: 
77629 
diff
changeset
 | 
63  | 
}  | 
| 
 
86ef80d13544
clarified signature: avoid confusion due to object-orientation;
 
wenzelm 
parents: 
77629 
diff
changeset
 | 
64  | 
|
| 78238 | 65  | 
sealed case class Result(  | 
| 77651 | 66  | 
name: String,  | 
67  | 
worker_uuid: String,  | 
|
68  | 
build_uuid: String,  | 
|
69  | 
node_info: Host.Node_Info,  | 
|
| 77461 | 70  | 
process_result: Process_Result,  | 
| 
77460
 
ccca589d7027
tuned signature: support general Build_Job instances;
 
wenzelm 
parents: 
77459 
diff
changeset
 | 
71  | 
output_shasum: SHA1.Shasum,  | 
| 77461 | 72  | 
current: Boolean  | 
| 
77652
 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 
wenzelm 
parents: 
77651 
diff
changeset
 | 
73  | 
  ) extends Library.Named {
 | 
| 
77259
 
61fc2afe4c8b
clarified signature: prefer stateful object-oriented style, to make it fit better into physical world;
 
wenzelm 
parents: 
77258 
diff
changeset
 | 
74  | 
def ok: Boolean = process_result.ok  | 
| 
 
61fc2afe4c8b
clarified signature: prefer stateful object-oriented style, to make it fit better into physical world;
 
wenzelm 
parents: 
77258 
diff
changeset
 | 
75  | 
}  | 
| 77312 | 76  | 
|
| 
78237
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
77  | 
  object Sessions {
 | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
78  | 
type Graph = isabelle.Graph[String, Build_Job.Session_Context]  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
79  | 
val empty: Sessions = new Sessions(Graph.string)  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
80  | 
}  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
81  | 
|
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
82  | 
  final class Sessions private(val graph: Sessions.Graph) {
 | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
83  | 
override def toString: String = graph.toString  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
84  | 
|
| 
78500
 
fc6d8a2895ca
more robust ancestor_results: avoid total existence failure after build_process has crashed elsewhere;
 
wenzelm 
parents: 
78440 
diff
changeset
 | 
85  | 
def defined(name: String): Boolean = graph.defined(name)  | 
| 
78237
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
86  | 
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: 
78234 
diff
changeset
 | 
87  | 
|
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
88  | 
def iterator: Iterator[Build_Job.Session_Context] =  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
89  | 
for (name <- graph.topological_order.iterator) yield apply(name)  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
90  | 
|
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
91  | 
def make(new_graph: Sessions.Graph): Sessions =  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
92  | 
if (graph == new_graph) this  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
93  | 
      else {
 | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
94  | 
new Sessions(  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
95  | 
          new_graph.iterator.foldLeft(new_graph) {
 | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
96  | 
case (g, (name, (session, _))) => g.add_deps_acyclic(name, session.deps)  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
97  | 
})  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
98  | 
}  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
99  | 
|
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
100  | 
def pull(  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
101  | 
data_domain: Set[String],  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
102  | 
data: Set[String] => List[Build_Job.Session_Context]  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
103  | 
    ): Sessions = {
 | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
104  | 
val dom = data_domain -- iterator.map(_.name)  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
105  | 
      make(data(dom).foldLeft(graph.restrict(dom)) { case (g, e) => g.new_node(e.name, e) })
 | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
106  | 
}  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
107  | 
|
| 78372 | 108  | 
def init(  | 
| 78421 | 109  | 
build_context: isabelle.Build.Context,  | 
| 78374 | 110  | 
database_server: Option[SQL.Database],  | 
111  | 
progress: Progress = new Progress  | 
|
| 78372 | 112  | 
    ): Sessions = {
 | 
| 
78237
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
113  | 
val sessions_structure = build_context.sessions_structure  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
114  | 
make(  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
115  | 
        sessions_structure.build_graph.iterator.foldLeft(graph) {
 | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
116  | 
case (graph0, (name, (info, _))) =>  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
117  | 
val deps = info.parent.toList  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
118  | 
val prefs = info.session_prefs  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
119  | 
val ancestors = sessions_structure.build_requirements(deps)  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
120  | 
val sources_shasum = build_context.build_deps.sources_shasum(name)  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
121  | 
|
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
122  | 
            if (graph0.defined(name)) {
 | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
123  | 
val session0 = graph0.get_node(name)  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
124  | 
val prefs0 = session0.session_prefs  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
125  | 
val ancestors0 = session0.ancestors  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
126  | 
val sources_shasum0 = session0.sources_shasum  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
127  | 
|
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
128  | 
def err(msg: String, a: String, b: String): Nothing =  | 
| 78501 | 129  | 
                error("Conflicting dependencies for session " + quote(name) + ": " + msg + "\n" +
 | 
130  | 
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: 
78234 
diff
changeset
 | 
131  | 
|
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
132  | 
              if (prefs0 != prefs) {
 | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
133  | 
                err("preferences disagree",
 | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
134  | 
Symbol.cartouche_decoded(prefs0), Symbol.cartouche_decoded(prefs))  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
135  | 
}  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
136  | 
              if (ancestors0 != ancestors) {
 | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
137  | 
                err("ancestors disagree", commas_quote(ancestors0), commas_quote(ancestors))
 | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
138  | 
}  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
139  | 
              if (sources_shasum0 != sources_shasum) {
 | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
140  | 
val a = sources_shasum0 - sources_shasum  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
141  | 
val b = sources_shasum - sources_shasum0  | 
| 78501 | 142  | 
                err("sources disagree",
 | 
143  | 
Library.trim_line(a.toString),  | 
|
144  | 
Library.trim_line(b.toString))  | 
|
| 
78237
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
145  | 
}  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
146  | 
|
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
147  | 
graph0  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
148  | 
}  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
149  | 
            else {
 | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
150  | 
val session =  | 
| 78374 | 151  | 
Build_Job.Session_Context.load(database_server,  | 
| 
78237
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
152  | 
build_context.build_uuid, name, deps, ancestors, prefs, sources_shasum,  | 
| 78374 | 153  | 
info.timeout, build_context.store, progress = progress)  | 
| 
78237
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
154  | 
graph0.new_node(name, session)  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
155  | 
}  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
156  | 
}  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
157  | 
)  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
158  | 
}  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
159  | 
|
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
160  | 
    lazy val max_time: Map[String, Double] = {
 | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
161  | 
val maximals = graph.maximals.toSet  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
162  | 
      def descendants_time(name: String): Double = {
 | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
163  | 
if (maximals.contains(name)) apply(name).old_time.seconds  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
164  | 
        else {
 | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
165  | 
val descendants = graph.all_succs(List(name)).toSet  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
166  | 
val g = graph.restrict(descendants)  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
167  | 
          (0.0 :: g.maximals.flatMap { desc =>
 | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
168  | 
val ps = g.all_preds(List(desc))  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
169  | 
if (ps.exists(p => !graph.defined(p))) None  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
170  | 
else Some(ps.map(p => apply(p).old_time.seconds).sum)  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
171  | 
}).max  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
172  | 
}  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
173  | 
}  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
174  | 
Map.from(  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
175  | 
for (name <- graph.keys_iterator)  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
176  | 
yield name -> descendants_time(name)).withDefaultValue(0.0)  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
177  | 
}  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
178  | 
|
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
179  | 
lazy val ordering: Ordering[String] =  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
180  | 
(a: String, b: String) =>  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
181  | 
        max_time(b) compare max_time(a) match {
 | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
182  | 
case 0 =>  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
183  | 
            apply(b).timeout compare apply(a).timeout match {
 | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
184  | 
case 0 => a compare b  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
185  | 
case ord => ord  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
186  | 
}  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
187  | 
case ord => ord  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
188  | 
}  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
189  | 
}  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
190  | 
|
| 
77659
 
d7eb6a4522b8
more explicit snapshot of "_state" and "_database";
 
wenzelm 
parents: 
77658 
diff
changeset
 | 
191  | 
sealed case class Snapshot(  | 
| 77660 | 192  | 
builds: List[Build], // available build configurations  | 
| 
77659
 
d7eb6a4522b8
more explicit snapshot of "_state" and "_database";
 
wenzelm 
parents: 
77658 
diff
changeset
 | 
193  | 
workers: List[Worker], // available worker processes  | 
| 
78237
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
194  | 
sessions: Sessions, // static build targets  | 
| 
77659
 
d7eb6a4522b8
more explicit snapshot of "_state" and "_database";
 
wenzelm 
parents: 
77658 
diff
changeset
 | 
195  | 
pending: State.Pending, // dynamic build "queue"  | 
| 
 
d7eb6a4522b8
more explicit snapshot of "_state" and "_database";
 
wenzelm 
parents: 
77658 
diff
changeset
 | 
196  | 
running: State.Running, // presently running jobs  | 
| 
 
d7eb6a4522b8
more explicit snapshot of "_state" and "_database";
 
wenzelm 
parents: 
77658 
diff
changeset
 | 
197  | 
results: State.Results) // finished results  | 
| 
 
d7eb6a4522b8
more explicit snapshot of "_state" and "_database";
 
wenzelm 
parents: 
77658 
diff
changeset
 | 
198  | 
|
| 77496 | 199  | 
  object State {
 | 
| 77585 | 200  | 
type Pending = List[Task]  | 
| 
77630
 
86ef80d13544
clarified signature: avoid confusion due to object-orientation;
 
wenzelm 
parents: 
77629 
diff
changeset
 | 
201  | 
type Running = Map[String, Job]  | 
| 77496 | 202  | 
type Results = Map[String, Result]  | 
203  | 
}  | 
|
204  | 
||
| 
77334
 
0231e62956a6
clarified state: more explicit type as plain value, which is also easier to sync with external db;
 
wenzelm 
parents: 
77333 
diff
changeset
 | 
205  | 
sealed case class State(  | 
| 77372 | 206  | 
serial: Long = 0,  | 
| 
78237
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
207  | 
numa_nodes: List[Int] = Nil,  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
208  | 
sessions: Sessions = Sessions.empty,  | 
| 
77659
 
d7eb6a4522b8
more explicit snapshot of "_state" and "_database";
 
wenzelm 
parents: 
77658 
diff
changeset
 | 
209  | 
pending: State.Pending = Nil,  | 
| 
 
d7eb6a4522b8
more explicit snapshot of "_state" and "_database";
 
wenzelm 
parents: 
77658 
diff
changeset
 | 
210  | 
running: State.Running = Map.empty,  | 
| 
 
d7eb6a4522b8
more explicit snapshot of "_state" and "_database";
 
wenzelm 
parents: 
77658 
diff
changeset
 | 
211  | 
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: 
77333 
diff
changeset
 | 
212  | 
  ) {
 | 
| 77513 | 213  | 
require(serial >= 0, "serial underflow")  | 
| 78574 | 214  | 
    def inc_serial: State = {
 | 
215  | 
require(serial < Long.MaxValue, "serial overflow")  | 
|
216  | 
copy(serial = serial + 1)  | 
|
| 77513 | 217  | 
}  | 
218  | 
||
| 
79020
 
ef76705bf402
clarified ready vs. next ready;
 
Fabian Huch <huch@in.tum.de> 
parents: 
78969 
diff
changeset
 | 
219  | 
def ready: State.Pending = pending.filter(_.is_ready)  | 
| 
 
ef76705bf402
clarified ready vs. next ready;
 
Fabian Huch <huch@in.tum.de> 
parents: 
78969 
diff
changeset
 | 
220  | 
def next_ready: State.Pending = ready.filter(entry => !is_running(entry.name))  | 
| 
78968
 
faa5af35fb65
clarified signature: more operations;
 
Fabian Huch <huch@in.tum.de> 
parents: 
78893 
diff
changeset
 | 
221  | 
|
| 
77334
 
0231e62956a6
clarified state: more explicit type as plain value, which is also easier to sync with external db;
 
wenzelm 
parents: 
77333 
diff
changeset
 | 
222  | 
def remove_pending(name: String): State =  | 
| 
 
0231e62956a6
clarified state: more explicit type as plain value, which is also easier to sync with external db;
 
wenzelm 
parents: 
77333 
diff
changeset
 | 
223  | 
copy(pending = pending.flatMap(  | 
| 
 
0231e62956a6
clarified state: more explicit type as plain value, which is also easier to sync with external db;
 
wenzelm 
parents: 
77333 
diff
changeset
 | 
224  | 
entry => if (entry.name == name) None else Some(entry.resolve(name))))  | 
| 
 
0231e62956a6
clarified state: more explicit type as plain value, which is also easier to sync with external db;
 
wenzelm 
parents: 
77333 
diff
changeset
 | 
225  | 
|
| 
 
0231e62956a6
clarified state: more explicit type as plain value, which is also easier to sync with external db;
 
wenzelm 
parents: 
77333 
diff
changeset
 | 
226  | 
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: 
77333 
diff
changeset
 | 
227  | 
|
| 
77630
 
86ef80d13544
clarified signature: avoid confusion due to object-orientation;
 
wenzelm 
parents: 
77629 
diff
changeset
 | 
228  | 
def stop_running(): Unit =  | 
| 
 
86ef80d13544
clarified signature: avoid confusion due to object-orientation;
 
wenzelm 
parents: 
77629 
diff
changeset
 | 
229  | 
for (job <- running.valuesIterator; build <- job.build) build.cancel()  | 
| 
77334
 
0231e62956a6
clarified state: more explicit type as plain value, which is also easier to sync with external db;
 
wenzelm 
parents: 
77333 
diff
changeset
 | 
230  | 
|
| 
78529
 
0e79fa88cab6
build_worker is stopped independently from master build_process;
 
wenzelm 
parents: 
78510 
diff
changeset
 | 
231  | 
def build_running: List[Build_Job] =  | 
| 
 
0e79fa88cab6
build_worker is stopped independently from master build_process;
 
wenzelm 
parents: 
78510 
diff
changeset
 | 
232  | 
List.from(for (job <- running.valuesIterator; build <- job.build) yield build)  | 
| 
 
0e79fa88cab6
build_worker is stopped independently from master build_process;
 
wenzelm 
parents: 
78510 
diff
changeset
 | 
233  | 
|
| 77649 | 234  | 
def finished_running(): List[Job] =  | 
| 
77630
 
86ef80d13544
clarified signature: avoid confusion due to object-orientation;
 
wenzelm 
parents: 
77629 
diff
changeset
 | 
235  | 
List.from(  | 
| 
 
86ef80d13544
clarified signature: avoid confusion due to object-orientation;
 
wenzelm 
parents: 
77629 
diff
changeset
 | 
236  | 
for (job <- running.valuesIterator; build <- job.build if build.is_finished)  | 
| 
78529
 
0e79fa88cab6
build_worker is stopped independently from master build_process;
 
wenzelm 
parents: 
78510 
diff
changeset
 | 
237  | 
yield job)  | 
| 
77334
 
0231e62956a6
clarified state: more explicit type as plain value, which is also easier to sync with external db;
 
wenzelm 
parents: 
77333 
diff
changeset
 | 
238  | 
|
| 
77630
 
86ef80d13544
clarified signature: avoid confusion due to object-orientation;
 
wenzelm 
parents: 
77629 
diff
changeset
 | 
239  | 
def add_running(job: Job): State =  | 
| 
 
86ef80d13544
clarified signature: avoid confusion due to object-orientation;
 
wenzelm 
parents: 
77629 
diff
changeset
 | 
240  | 
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: 
77333 
diff
changeset
 | 
241  | 
|
| 
 
0231e62956a6
clarified state: more explicit type as plain value, which is also easier to sync with external db;
 
wenzelm 
parents: 
77333 
diff
changeset
 | 
242  | 
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: 
77333 
diff
changeset
 | 
243  | 
copy(running = running - name)  | 
| 
 
0231e62956a6
clarified state: more explicit type as plain value, which is also easier to sync with external db;
 
wenzelm 
parents: 
77333 
diff
changeset
 | 
244  | 
|
| 77336 | 245  | 
def make_result(  | 
| 77651 | 246  | 
result_name: (String, String, String),  | 
| 77461 | 247  | 
process_result: Process_Result,  | 
| 
77460
 
ccca589d7027
tuned signature: support general Build_Job instances;
 
wenzelm 
parents: 
77459 
diff
changeset
 | 
248  | 
output_shasum: SHA1.Shasum,  | 
| 77475 | 249  | 
node_info: Host.Node_Info = Host.Node_Info.none,  | 
| 77461 | 250  | 
current: Boolean = false  | 
| 
77334
 
0231e62956a6
clarified state: more explicit type as plain value, which is also easier to sync with external db;
 
wenzelm 
parents: 
77333 
diff
changeset
 | 
251  | 
    ): State = {
 | 
| 77651 | 252  | 
val (name, worker_uuid, build_uuid) = result_name  | 
253  | 
val result =  | 
|
254  | 
Result(name, worker_uuid, build_uuid, node_info, process_result, output_shasum, current)  | 
|
255  | 
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: 
77333 
diff
changeset
 | 
256  | 
}  | 
| 
78500
 
fc6d8a2895ca
more robust ancestor_results: avoid total existence failure after build_process has crashed elsewhere;
 
wenzelm 
parents: 
78440 
diff
changeset
 | 
257  | 
|
| 
 
fc6d8a2895ca
more robust ancestor_results: avoid total existence failure after build_process has crashed elsewhere;
 
wenzelm 
parents: 
78440 
diff
changeset
 | 
258  | 
    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: 
78440 
diff
changeset
 | 
259  | 
val defined =  | 
| 
 
fc6d8a2895ca
more robust ancestor_results: avoid total existence failure after build_process has crashed elsewhere;
 
wenzelm 
parents: 
78440 
diff
changeset
 | 
260  | 
sessions.defined(name) &&  | 
| 
 
fc6d8a2895ca
more robust ancestor_results: avoid total existence failure after build_process has crashed elsewhere;
 
wenzelm 
parents: 
78440 
diff
changeset
 | 
261  | 
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: 
78440 
diff
changeset
 | 
262  | 
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: 
78440 
diff
changeset
 | 
263  | 
}  | 
| 
77334
 
0231e62956a6
clarified state: more explicit type as plain value, which is also easier to sync with external db;
 
wenzelm 
parents: 
77333 
diff
changeset
 | 
264  | 
}  | 
| 
 
0231e62956a6
clarified state: more explicit type as plain value, which is also easier to sync with external db;
 
wenzelm 
parents: 
77333 
diff
changeset
 | 
265  | 
|
| 
 
0231e62956a6
clarified state: more explicit type as plain value, which is also easier to sync with external db;
 
wenzelm 
parents: 
77333 
diff
changeset
 | 
266  | 
|
| 77436 | 267  | 
|
268  | 
/** SQL data model **/  | 
|
| 77372 | 269  | 
|
| 
78396
 
7853d9072d1b
renamed object Data to private_data, to emphasize its intended scope (but it is publicly accessible in the database);
 
wenzelm 
parents: 
78394 
diff
changeset
 | 
270  | 
  object private_data extends SQL.Data("isabelle_build") {
 | 
| 78168 | 271  | 
    val database: Path = Path.explode("$ISABELLE_HOME_USER/build.db")
 | 
272  | 
||
| 78244 | 273  | 
def pull[A <: Library.Named](  | 
| 
77652
 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 
wenzelm 
parents: 
77651 
diff
changeset
 | 
274  | 
data_domain: Set[String],  | 
| 
 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 
wenzelm 
parents: 
77651 
diff
changeset
 | 
275  | 
data_iterator: Set[String] => Iterator[A],  | 
| 
 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 
wenzelm 
parents: 
77651 
diff
changeset
 | 
276  | 
old_data: Map[String, A]  | 
| 
 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 
wenzelm 
parents: 
77651 
diff
changeset
 | 
277  | 
    ): Map[String, A] = {
 | 
| 
 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 
wenzelm 
parents: 
77651 
diff
changeset
 | 
278  | 
val dom = data_domain -- old_data.keysIterator  | 
| 78268 | 279  | 
val data = old_data -- old_data.keysIterator.filterNot(data_domain)  | 
| 
77652
 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 
wenzelm 
parents: 
77651 
diff
changeset
 | 
280  | 
if (dom.isEmpty) data  | 
| 
 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 
wenzelm 
parents: 
77651 
diff
changeset
 | 
281  | 
      else data_iterator(dom).foldLeft(data) { case (map, a) => map + (a.name -> a) }
 | 
| 
 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 
wenzelm 
parents: 
77651 
diff
changeset
 | 
282  | 
}  | 
| 
 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 
wenzelm 
parents: 
77651 
diff
changeset
 | 
283  | 
|
| 
 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 
wenzelm 
parents: 
77651 
diff
changeset
 | 
284  | 
def pull0[A <: Library.Named](  | 
| 
 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 
wenzelm 
parents: 
77651 
diff
changeset
 | 
285  | 
new_data: Map[String, A],  | 
| 
 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 
wenzelm 
parents: 
77651 
diff
changeset
 | 
286  | 
old_data: Map[String, A]  | 
| 
 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 
wenzelm 
parents: 
77651 
diff
changeset
 | 
287  | 
    ): Map[String, A] = {
 | 
| 78244 | 288  | 
pull(new_data.keySet, dom => new_data.valuesIterator.filter(a => dom(a.name)), old_data)  | 
| 
77652
 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 
wenzelm 
parents: 
77651 
diff
changeset
 | 
289  | 
}  | 
| 
 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 
wenzelm 
parents: 
77651 
diff
changeset
 | 
290  | 
|
| 
 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 
wenzelm 
parents: 
77651 
diff
changeset
 | 
291  | 
def pull1[A <: Library.Named](  | 
| 
 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 
wenzelm 
parents: 
77651 
diff
changeset
 | 
292  | 
data_domain: Set[String],  | 
| 
 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 
wenzelm 
parents: 
77651 
diff
changeset
 | 
293  | 
data_base: Set[String] => Map[String, A],  | 
| 
 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 
wenzelm 
parents: 
77651 
diff
changeset
 | 
294  | 
old_data: Map[String, A]  | 
| 
 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 
wenzelm 
parents: 
77651 
diff
changeset
 | 
295  | 
    ): Map[String, A] = {
 | 
| 78244 | 296  | 
pull(data_domain, dom => data_base(dom).valuesIterator, old_data)  | 
| 
77652
 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 
wenzelm 
parents: 
77651 
diff
changeset
 | 
297  | 
}  | 
| 
 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 
wenzelm 
parents: 
77651 
diff
changeset
 | 
298  | 
|
| 77372 | 299  | 
    object Generic {
 | 
| 
77529
 
40ccee0fe19a
separate static build_uuid from dynamic worker_uuid, to allow multiple worker processes participate in one build process;
 
wenzelm 
parents: 
77527 
diff
changeset
 | 
300  | 
      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: 
77527 
diff
changeset
 | 
301  | 
      val worker_uuid = SQL.Column.string("worker_uuid")
 | 
| 77372 | 302  | 
      val name = SQL.Column.string("name")
 | 
303  | 
||
| 
77529
 
40ccee0fe19a
separate static build_uuid from dynamic worker_uuid, to allow multiple worker processes participate in one build process;
 
wenzelm 
parents: 
77527 
diff
changeset
 | 
304  | 
def sql(  | 
| 
 
40ccee0fe19a
separate static build_uuid from dynamic worker_uuid, to allow multiple worker processes participate in one build process;
 
wenzelm 
parents: 
77527 
diff
changeset
 | 
305  | 
build_uuid: String = "",  | 
| 
 
40ccee0fe19a
separate static build_uuid from dynamic worker_uuid, to allow multiple worker processes participate in one build process;
 
wenzelm 
parents: 
77527 
diff
changeset
 | 
306  | 
worker_uuid: String = "",  | 
| 
 
40ccee0fe19a
separate static build_uuid from dynamic worker_uuid, to allow multiple worker processes participate in one build process;
 
wenzelm 
parents: 
77527 
diff
changeset
 | 
307  | 
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: 
77527 
diff
changeset
 | 
308  | 
): SQL.Source =  | 
| 77372 | 309  | 
SQL.and(  | 
| 
77529
 
40ccee0fe19a
separate static build_uuid from dynamic worker_uuid, to allow multiple worker processes participate in one build process;
 
wenzelm 
parents: 
77527 
diff
changeset
 | 
310  | 
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: 
77527 
diff
changeset
 | 
311  | 
if_proper(worker_uuid, Generic.worker_uuid.equal(worker_uuid)),  | 
| 77375 | 312  | 
if_proper(names, Generic.name.member(names)))  | 
| 77662 | 313  | 
|
314  | 
def sql_where(  | 
|
315  | 
build_uuid: String = "",  | 
|
316  | 
worker_uuid: String = "",  | 
|
317  | 
names: Iterable[String] = Nil  | 
|
318  | 
      ): SQL.Source = {
 | 
|
| 77663 | 319  | 
SQL.where(sql(build_uuid = build_uuid, worker_uuid = worker_uuid, names = names))  | 
| 77662 | 320  | 
}  | 
| 77372 | 321  | 
}  | 
322  | 
||
| 
77536
 
7c7f1473e51a
clarified database content and prepare/init stages;
 
wenzelm 
parents: 
77534 
diff
changeset
 | 
323  | 
|
| 
 
7c7f1473e51a
clarified database content and prepare/init stages;
 
wenzelm 
parents: 
77534 
diff
changeset
 | 
324  | 
/* base table */  | 
| 
 
7c7f1473e51a
clarified database content and prepare/init stages;
 
wenzelm 
parents: 
77534 
diff
changeset
 | 
325  | 
|
| 77417 | 326  | 
    object Base {
 | 
| 
77529
 
40ccee0fe19a
separate static build_uuid from dynamic worker_uuid, to allow multiple worker processes participate in one build process;
 
wenzelm 
parents: 
77527 
diff
changeset
 | 
327  | 
val build_uuid = Generic.build_uuid.make_primary_key  | 
| 
77387
 
cd10b8edfdf5
clarified db content: avoid redundancy of historic ML_IDENTIFIER;
 
wenzelm 
parents: 
77385 
diff
changeset
 | 
328  | 
      val ml_platform = SQL.Column.string("ml_platform")
 | 
| 77372 | 329  | 
      val options = SQL.Column.string("options")
 | 
| 
77536
 
7c7f1473e51a
clarified database content and prepare/init stages;
 
wenzelm 
parents: 
77534 
diff
changeset
 | 
330  | 
      val start = SQL.Column.date("start")
 | 
| 77545 | 331  | 
      val stop = SQL.Column.date("stop")
 | 
| 77372 | 332  | 
|
| 78266 | 333  | 
val table = make_table(List(build_uuid, ml_platform, options, start, stop))  | 
| 
77536
 
7c7f1473e51a
clarified database content and prepare/init stages;
 
wenzelm 
parents: 
77534 
diff
changeset
 | 
334  | 
}  | 
| 
 
7c7f1473e51a
clarified database content and prepare/init stages;
 
wenzelm 
parents: 
77534 
diff
changeset
 | 
335  | 
|
| 78632 | 336  | 
    def read_builds(db: SQL.Database): List[Build] = {
 | 
| 78226 | 337  | 
val builds =  | 
| 78632 | 338  | 
db.execute_query_statement(Base.table.select(), List.from[Build],  | 
| 78226 | 339  | 
          { res =>
 | 
340  | 
val build_uuid = res.string(Base.build_uuid)  | 
|
341  | 
val ml_platform = res.string(Base.ml_platform)  | 
|
342  | 
val options = res.string(Base.options)  | 
|
343  | 
val start = res.date(Base.start)  | 
|
344  | 
val stop = res.get_date(Base.stop)  | 
|
345  | 
Build(build_uuid, ml_platform, options, start, stop, Nil)  | 
|
346  | 
})  | 
|
347  | 
||
348  | 
      for (build <- builds.sortBy(_.start)(Date.Ordering)) yield {
 | 
|
| 
78396
 
7853d9072d1b
renamed object Data to private_data, to emphasize its intended scope (but it is publicly accessible in the database);
 
wenzelm 
parents: 
78394 
diff
changeset
 | 
349  | 
val sessions = private_data.read_sessions_domain(db, build_uuid = build.build_uuid)  | 
| 78226 | 350  | 
build.copy(sessions = sessions.toList.sorted)  | 
351  | 
}  | 
|
352  | 
}  | 
|
| 77660 | 353  | 
|
| 78635 | 354  | 
def remove_builds(db: SQL.Database, remove: List[String]): Unit =  | 
355  | 
      if (remove.nonEmpty) {
 | 
|
356  | 
val sql = Generic.build_uuid.where_member(remove)  | 
|
357  | 
db.execute_statement(SQL.MULTI(build_uuid_tables.map(_.delete(sql = sql))))  | 
|
358  | 
}  | 
|
359  | 
||
| 
77536
 
7c7f1473e51a
clarified database content and prepare/init stages;
 
wenzelm 
parents: 
77534 
diff
changeset
 | 
360  | 
def start_build(  | 
| 
 
7c7f1473e51a
clarified database content and prepare/init stages;
 
wenzelm 
parents: 
77534 
diff
changeset
 | 
361  | 
db: SQL.Database,  | 
| 
 
7c7f1473e51a
clarified database content and prepare/init stages;
 
wenzelm 
parents: 
77534 
diff
changeset
 | 
362  | 
build_uuid: String,  | 
| 
 
7c7f1473e51a
clarified database content and prepare/init stages;
 
wenzelm 
parents: 
77534 
diff
changeset
 | 
363  | 
ml_platform: String,  | 
| 
78156
 
da5cc332ded3
prefer Database_Progress, which is more robust (amending afb1a19307c4);
 
wenzelm 
parents: 
78154 
diff
changeset
 | 
364  | 
options: String  | 
| 
77536
 
7c7f1473e51a
clarified database content and prepare/init stages;
 
wenzelm 
parents: 
77534 
diff
changeset
 | 
365  | 
    ): Unit = {
 | 
| 77541 | 366  | 
db.execute_statement(Base.table.insert(), body =  | 
367  | 
        { stmt =>
 | 
|
368  | 
stmt.string(1) = build_uuid  | 
|
369  | 
stmt.string(2) = ml_platform  | 
|
370  | 
stmt.string(3) = options  | 
|
371  | 
stmt.date(4) = db.now()  | 
|
372  | 
stmt.date(5) = None  | 
|
373  | 
})  | 
|
| 77372 | 374  | 
}  | 
375  | 
||
| 77545 | 376  | 
def stop_build(db: SQL.Database, build_uuid: String): Unit =  | 
| 77541 | 377  | 
db.execute_statement(  | 
| 77636 | 378  | 
Base.table.update(List(Base.stop), sql = Base.build_uuid.where_equal(build_uuid)),  | 
| 77541 | 379  | 
        body = { stmt => stmt.date(1) = db.now() })
 | 
| 77538 | 380  | 
|
| 
77539
 
2b996a0df1ce
proper clean_build of old data at start of new process --- allow to inspect remains of the last process;
 
wenzelm 
parents: 
77538 
diff
changeset
 | 
381  | 
    def clean_build(db: SQL.Database): Unit = {
 | 
| 78635 | 382  | 
val remove =  | 
| 77552 | 383  | 
db.execute_query_statement(  | 
384  | 
Base.table.select(List(Base.build_uuid), sql = SQL.where(Base.stop.defined)),  | 
|
385  | 
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: 
77538 
diff
changeset
 | 
386  | 
|
| 78635 | 387  | 
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: 
77538 
diff
changeset
 | 
388  | 
}  | 
| 
 
2b996a0df1ce
proper clean_build of old data at start of new process --- allow to inspect remains of the last process;
 
wenzelm 
parents: 
77538 
diff
changeset
 | 
389  | 
|
| 
77416
 
d88c12f22ab0
clarified scope of "serial" and "numa_index" within database;
 
wenzelm 
parents: 
77415 
diff
changeset
 | 
390  | 
|
| 77531 | 391  | 
/* sessions */  | 
| 77505 | 392  | 
|
| 77496 | 393  | 
    object Sessions {
 | 
394  | 
val name = Generic.name.make_primary_key  | 
|
395  | 
      val deps = SQL.Column.string("deps")
 | 
|
396  | 
      val ancestors = SQL.Column.string("ancestors")
 | 
|
| 
77610
 
3b09ae9e40cb
clarified session prefs (or "options" within the database);
 
wenzelm 
parents: 
77609 
diff
changeset
 | 
397  | 
      val options = SQL.Column.string("options")
 | 
| 77496 | 398  | 
      val sources = SQL.Column.string("sources")
 | 
399  | 
      val timeout = SQL.Column.long("timeout")
 | 
|
400  | 
      val old_time = SQL.Column.long("old_time")
 | 
|
401  | 
      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: 
77527 
diff
changeset
 | 
402  | 
val build_uuid = Generic.build_uuid  | 
| 77496 | 403  | 
|
| 78266 | 404  | 
val table =  | 
405  | 
make_table(  | 
|
406  | 
List(name, deps, ancestors, options, sources, timeout,  | 
|
407  | 
old_time, old_command_timings, build_uuid),  | 
|
408  | 
name = "sessions")  | 
|
| 77496 | 409  | 
}  | 
410  | 
||
| 
78218
 
a625bfb0e549
clarified signature: more operations and options;
 
wenzelm 
parents: 
78217 
diff
changeset
 | 
411  | 
def read_sessions_domain(db: SQL.Database, build_uuid: String = ""): Set[String] =  | 
| 77552 | 412  | 
db.execute_query_statement(  | 
| 
78218
 
a625bfb0e549
clarified signature: more operations and options;
 
wenzelm 
parents: 
78217 
diff
changeset
 | 
413  | 
Sessions.table.select(List(Sessions.name),  | 
| 78251 | 414  | 
sql = if_proper(build_uuid, Sessions.build_uuid.where_equal(build_uuid))),  | 
| 77552 | 415  | 
Set.from[String], res => res.string(Sessions.name))  | 
| 77496 | 416  | 
|
| 
78218
 
a625bfb0e549
clarified signature: more operations and options;
 
wenzelm 
parents: 
78217 
diff
changeset
 | 
417  | 
def read_sessions(db: SQL.Database,  | 
| 
 
a625bfb0e549
clarified signature: more operations and options;
 
wenzelm 
parents: 
78217 
diff
changeset
 | 
418  | 
names: Iterable[String] = Nil,  | 
| 
 
a625bfb0e549
clarified signature: more operations and options;
 
wenzelm 
parents: 
78217 
diff
changeset
 | 
419  | 
build_uuid: String = ""  | 
| 
78237
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
420  | 
    ): List[Build_Job.Session_Context] = {
 | 
| 77552 | 421  | 
db.execute_query_statement(  | 
| 
78218
 
a625bfb0e549
clarified signature: more operations and options;
 
wenzelm 
parents: 
78217 
diff
changeset
 | 
422  | 
Sessions.table.select(  | 
| 
 
a625bfb0e549
clarified signature: more operations and options;
 
wenzelm 
parents: 
78217 
diff
changeset
 | 
423  | 
sql =  | 
| 
 
a625bfb0e549
clarified signature: more operations and options;
 
wenzelm 
parents: 
78217 
diff
changeset
 | 
424  | 
SQL.where_and(  | 
| 
 
a625bfb0e549
clarified signature: more operations and options;
 
wenzelm 
parents: 
78217 
diff
changeset
 | 
425  | 
if_proper(names, Sessions.name.member(names)),  | 
| 
 
a625bfb0e549
clarified signature: more operations and options;
 
wenzelm 
parents: 
78217 
diff
changeset
 | 
426  | 
if_proper(build_uuid, Sessions.build_uuid.equal(build_uuid)))  | 
| 
 
a625bfb0e549
clarified signature: more operations and options;
 
wenzelm 
parents: 
78217 
diff
changeset
 | 
427  | 
),  | 
| 
78237
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
428  | 
List.from[Build_Job.Session_Context],  | 
| 77552 | 429  | 
        { res =>
 | 
430  | 
val name = res.string(Sessions.name)  | 
|
431  | 
val deps = split_lines(res.string(Sessions.deps))  | 
|
432  | 
val ancestors = split_lines(res.string(Sessions.ancestors))  | 
|
| 
77610
 
3b09ae9e40cb
clarified session prefs (or "options" within the database);
 
wenzelm 
parents: 
77609 
diff
changeset
 | 
433  | 
val options = res.string(Sessions.options)  | 
| 77552 | 434  | 
val sources_shasum = SHA1.fake_shasum(res.string(Sessions.sources))  | 
435  | 
val timeout = Time.ms(res.long(Sessions.timeout))  | 
|
436  | 
val old_time = Time.ms(res.long(Sessions.old_time))  | 
|
437  | 
val old_command_timings_blob = res.bytes(Sessions.old_command_timings)  | 
|
438  | 
val build_uuid = res.string(Sessions.build_uuid)  | 
|
| 
78237
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
439  | 
Build_Job.Session_Context(name, deps, ancestors, options, sources_shasum,  | 
| 77552 | 440  | 
timeout, old_time, old_command_timings_blob, build_uuid)  | 
| 77496 | 441  | 
}  | 
| 77552 | 442  | 
)  | 
| 
78237
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
443  | 
}  | 
| 77496 | 444  | 
|
| 78553 | 445  | 
def update_sessions(  | 
446  | 
db: SQL.Database,  | 
|
447  | 
sessions: Build_Process.Sessions,  | 
|
448  | 
old_sessions: Build_Process.Sessions  | 
|
449  | 
    ): Boolean = {
 | 
|
450  | 
val insert = sessions.iterator.filterNot(s => old_sessions.defined(s.name)).toList  | 
|
| 77496 | 451  | 
|
| 
78552
 
384adc74e27d
performance tuning: avoid multiple db roundtrips;
 
wenzelm 
parents: 
78546 
diff
changeset
 | 
452  | 
      if (insert.nonEmpty) {
 | 
| 
 
384adc74e27d
performance tuning: avoid multiple db roundtrips;
 
wenzelm 
parents: 
78546 
diff
changeset
 | 
453  | 
db.execute_batch_statement(Sessions.table.insert(), batch =  | 
| 
 
384adc74e27d
performance tuning: avoid multiple db roundtrips;
 
wenzelm 
parents: 
78546 
diff
changeset
 | 
454  | 
          for (session <- insert) yield { (stmt: SQL.Statement) =>
 | 
| 
78237
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
455  | 
stmt.string(1) = session.name  | 
| 77541 | 456  | 
stmt.string(2) = cat_lines(session.deps)  | 
457  | 
stmt.string(3) = cat_lines(session.ancestors)  | 
|
| 
77610
 
3b09ae9e40cb
clarified session prefs (or "options" within the database);
 
wenzelm 
parents: 
77609 
diff
changeset
 | 
458  | 
stmt.string(4) = session.session_prefs  | 
| 
 
3b09ae9e40cb
clarified session prefs (or "options" within the database);
 
wenzelm 
parents: 
77609 
diff
changeset
 | 
459  | 
stmt.string(5) = session.sources_shasum.toString  | 
| 
 
3b09ae9e40cb
clarified session prefs (or "options" within the database);
 
wenzelm 
parents: 
77609 
diff
changeset
 | 
460  | 
stmt.long(6) = session.timeout.ms  | 
| 
 
3b09ae9e40cb
clarified session prefs (or "options" within the database);
 
wenzelm 
parents: 
77609 
diff
changeset
 | 
461  | 
stmt.long(7) = session.old_time.ms  | 
| 
 
3b09ae9e40cb
clarified session prefs (or "options" within the database);
 
wenzelm 
parents: 
77609 
diff
changeset
 | 
462  | 
stmt.bytes(8) = session.old_command_timings_blob  | 
| 
 
3b09ae9e40cb
clarified session prefs (or "options" within the database);
 
wenzelm 
parents: 
77609 
diff
changeset
 | 
463  | 
stmt.string(9) = session.build_uuid  | 
| 77541 | 464  | 
})  | 
| 77496 | 465  | 
}  | 
466  | 
||
467  | 
insert.nonEmpty  | 
|
468  | 
}  | 
|
469  | 
||
| 77531 | 470  | 
|
471  | 
/* workers */  | 
|
472  | 
||
473  | 
    object Workers {
 | 
|
| 78173 | 474  | 
val worker_uuid = Generic.worker_uuid.make_primary_key  | 
475  | 
val build_uuid = Generic.build_uuid  | 
|
| 
77546
 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 
wenzelm 
parents: 
77545 
diff
changeset
 | 
476  | 
      val start = SQL.Column.date("start")
 | 
| 77531 | 477  | 
      val stamp = SQL.Column.date("stamp")
 | 
| 
77546
 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 
wenzelm 
parents: 
77545 
diff
changeset
 | 
478  | 
      val stop = SQL.Column.date("stop")
 | 
| 77531 | 479  | 
      val serial = SQL.Column.long("serial")
 | 
480  | 
||
| 78266 | 481  | 
val table =  | 
482  | 
make_table(List(worker_uuid, build_uuid, start, stamp, stop, serial), name = "workers")  | 
|
| 77531 | 483  | 
}  | 
484  | 
||
| 77655 | 485  | 
def read_serial(db: SQL.Database): Long =  | 
486  | 
db.execute_query_statementO[Long](  | 
|
| 78151 | 487  | 
Workers.table.select(List(Workers.serial.max)), _.long(Workers.serial)).getOrElse(0L)  | 
| 77655 | 488  | 
|
| 77586 | 489  | 
def read_workers(  | 
490  | 
db: SQL.Database,  | 
|
491  | 
build_uuid: String = "",  | 
|
492  | 
worker_uuid: String = ""  | 
|
| 
77657
 
a2a4adc268b8
removed redundant State.workers: directly maintained within the database, using with SQL update;
 
wenzelm 
parents: 
77656 
diff
changeset
 | 
493  | 
    ): List[Worker] = {
 | 
| 77586 | 494  | 
db.execute_query_statement(  | 
| 77662 | 495  | 
Workers.table.select(  | 
496  | 
sql = Generic.sql_where(build_uuid = build_uuid, worker_uuid = worker_uuid)),  | 
|
| 77586 | 497  | 
List.from[Worker],  | 
498  | 
          { res =>
 | 
|
499  | 
Worker(  | 
|
500  | 
worker_uuid = res.string(Workers.worker_uuid),  | 
|
501  | 
build_uuid = res.string(Workers.build_uuid),  | 
|
502  | 
start = res.date(Workers.start),  | 
|
503  | 
stamp = res.date(Workers.stamp),  | 
|
504  | 
stop = res.get_date(Workers.stop),  | 
|
505  | 
serial = res.long(Workers.serial))  | 
|
506  | 
})  | 
|
507  | 
}  | 
|
508  | 
||
| 77584 | 509  | 
def start_worker(  | 
510  | 
db: SQL.Database,  | 
|
511  | 
worker_uuid: String,  | 
|
512  | 
build_uuid: String,  | 
|
| 
77652
 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 
wenzelm 
parents: 
77651 
diff
changeset
 | 
513  | 
serial: Long  | 
| 
 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 
wenzelm 
parents: 
77651 
diff
changeset
 | 
514  | 
    ): Unit = {
 | 
| 
77546
 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 
wenzelm 
parents: 
77545 
diff
changeset
 | 
515  | 
def err(msg: String): Nothing =  | 
| 
 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 
wenzelm 
parents: 
77545 
diff
changeset
 | 
516  | 
        error("Cannot start worker " + worker_uuid + if_proper(msg, "\n" + msg))
 | 
| 
 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 
wenzelm 
parents: 
77545 
diff
changeset
 | 
517  | 
|
| 77552 | 518  | 
val build_stop =  | 
519  | 
db.execute_query_statementO(  | 
|
| 77636 | 520  | 
Base.table.select(List(Base.stop), sql = Base.build_uuid.where_equal(build_uuid)),  | 
| 77552 | 521  | 
res => res.get_date(Base.stop))  | 
522  | 
||
| 
77546
 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 
wenzelm 
parents: 
77545 
diff
changeset
 | 
523  | 
      build_stop match {
 | 
| 
 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 
wenzelm 
parents: 
77545 
diff
changeset
 | 
524  | 
case Some(None) =>  | 
| 
 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 
wenzelm 
parents: 
77545 
diff
changeset
 | 
525  | 
        case Some(Some(_)) => err("for already stopped build process " + build_uuid)
 | 
| 
 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 
wenzelm 
parents: 
77545 
diff
changeset
 | 
526  | 
        case None => err("for unknown build process " + build_uuid)
 | 
| 77531 | 527  | 
}  | 
528  | 
||
| 
77546
 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 
wenzelm 
parents: 
77545 
diff
changeset
 | 
529  | 
db.execute_statement(Workers.table.insert(), body =  | 
| 
 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 
wenzelm 
parents: 
77545 
diff
changeset
 | 
530  | 
        { stmt =>
 | 
| 
 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 
wenzelm 
parents: 
77545 
diff
changeset
 | 
531  | 
val now = db.now()  | 
| 
 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 
wenzelm 
parents: 
77545 
diff
changeset
 | 
532  | 
stmt.string(1) = worker_uuid  | 
| 
 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 
wenzelm 
parents: 
77545 
diff
changeset
 | 
533  | 
stmt.string(2) = build_uuid  | 
| 
78172
 
43ed2541b758
omit redundant data: already stored in progress database;
 
wenzelm 
parents: 
78170 
diff
changeset
 | 
534  | 
stmt.date(3) = now  | 
| 
 
43ed2541b758
omit redundant data: already stored in progress database;
 
wenzelm 
parents: 
78170 
diff
changeset
 | 
535  | 
stmt.date(4) = now  | 
| 
 
43ed2541b758
omit redundant data: already stored in progress database;
 
wenzelm 
parents: 
78170 
diff
changeset
 | 
536  | 
stmt.date(5) = None  | 
| 
 
43ed2541b758
omit redundant data: already stored in progress database;
 
wenzelm 
parents: 
78170 
diff
changeset
 | 
537  | 
stmt.long(6) = serial  | 
| 
77546
 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 
wenzelm 
parents: 
77545 
diff
changeset
 | 
538  | 
})  | 
| 
 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 
wenzelm 
parents: 
77545 
diff
changeset
 | 
539  | 
}  | 
| 
 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 
wenzelm 
parents: 
77545 
diff
changeset
 | 
540  | 
|
| 
 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 
wenzelm 
parents: 
77545 
diff
changeset
 | 
541  | 
def stamp_worker(  | 
| 
 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 
wenzelm 
parents: 
77545 
diff
changeset
 | 
542  | 
db: SQL.Database,  | 
| 
 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 
wenzelm 
parents: 
77545 
diff
changeset
 | 
543  | 
worker_uuid: String,  | 
| 
 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 
wenzelm 
parents: 
77545 
diff
changeset
 | 
544  | 
serial: Long,  | 
| 
78246
 
76dd9b9cf624
more robust "stop": further "stamp" ticks may happen afterwards;
 
wenzelm 
parents: 
78245 
diff
changeset
 | 
545  | 
stop_now: Boolean = false  | 
| 
77546
 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 
wenzelm 
parents: 
77545 
diff
changeset
 | 
546  | 
    ): Unit = {
 | 
| 
78246
 
76dd9b9cf624
more robust "stop": further "stamp" ticks may happen afterwards;
 
wenzelm 
parents: 
78245 
diff
changeset
 | 
547  | 
val sql = Workers.worker_uuid.where_equal(worker_uuid)  | 
| 
 
76dd9b9cf624
more robust "stop": further "stamp" ticks may happen afterwards;
 
wenzelm 
parents: 
78245 
diff
changeset
 | 
548  | 
|
| 
 
76dd9b9cf624
more robust "stop": further "stamp" ticks may happen afterwards;
 
wenzelm 
parents: 
78245 
diff
changeset
 | 
549  | 
val stop =  | 
| 
 
76dd9b9cf624
more robust "stop": further "stamp" ticks may happen afterwards;
 
wenzelm 
parents: 
78245 
diff
changeset
 | 
550  | 
db.execute_query_statementO(  | 
| 
 
76dd9b9cf624
more robust "stop": further "stamp" ticks may happen afterwards;
 
wenzelm 
parents: 
78245 
diff
changeset
 | 
551  | 
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: 
78245 
diff
changeset
 | 
552  | 
|
| 78241 | 553  | 
db.execute_statement(  | 
| 
78246
 
76dd9b9cf624
more robust "stop": further "stamp" ticks may happen afterwards;
 
wenzelm 
parents: 
78245 
diff
changeset
 | 
554  | 
Workers.table.update(List(Workers.stamp, Workers.stop, Workers.serial), sql = sql),  | 
| 78241 | 555  | 
        body = { stmt =>
 | 
| 
77546
 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 
wenzelm 
parents: 
77545 
diff
changeset
 | 
556  | 
val now = db.now()  | 
| 
 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 
wenzelm 
parents: 
77545 
diff
changeset
 | 
557  | 
stmt.date(1) = now  | 
| 
78246
 
76dd9b9cf624
more robust "stop": further "stamp" ticks may happen afterwards;
 
wenzelm 
parents: 
78245 
diff
changeset
 | 
558  | 
stmt.date(2) = if (stop_now) Some(now) else stop  | 
| 
77546
 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 
wenzelm 
parents: 
77545 
diff
changeset
 | 
559  | 
stmt.long(3) = serial  | 
| 
 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 
wenzelm 
parents: 
77545 
diff
changeset
 | 
560  | 
})  | 
| 
 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 
wenzelm 
parents: 
77545 
diff
changeset
 | 
561  | 
}  | 
| 
 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 
wenzelm 
parents: 
77545 
diff
changeset
 | 
562  | 
|
| 77531 | 563  | 
|
564  | 
/* pending jobs */  | 
|
565  | 
||
566  | 
    object Pending {
 | 
|
567  | 
val name = Generic.name.make_primary_key  | 
|
568  | 
      val deps = SQL.Column.string("deps")
 | 
|
569  | 
      val info = SQL.Column.string("info")
 | 
|
| 
77661
 
45bd5c26cbcc
proper build_uuid for Build_Process.Task: thus old entries are removed via prepare_database/clean_build;
 
wenzelm 
parents: 
77660 
diff
changeset
 | 
570  | 
val build_uuid = Generic.build_uuid  | 
| 77531 | 571  | 
|
| 78266 | 572  | 
val table = make_table(List(name, deps, info, build_uuid), name = "pending")  | 
| 77531 | 573  | 
}  | 
574  | 
||
| 77585 | 575  | 
def read_pending(db: SQL.Database): List[Task] =  | 
| 77552 | 576  | 
db.execute_query_statement(  | 
577  | 
Pending.table.select(sql = SQL.order_by(List(Pending.name))),  | 
|
| 77585 | 578  | 
List.from[Task],  | 
| 77552 | 579  | 
        { res =>
 | 
580  | 
val name = res.string(Pending.name)  | 
|
581  | 
val deps = res.string(Pending.deps)  | 
|
582  | 
val info = res.string(Pending.info)  | 
|
| 
77661
 
45bd5c26cbcc
proper build_uuid for Build_Process.Task: thus old entries are removed via prepare_database/clean_build;
 
wenzelm 
parents: 
77660 
diff
changeset
 | 
583  | 
val build_uuid = res.string(Pending.build_uuid)  | 
| 
 
45bd5c26cbcc
proper build_uuid for Build_Process.Task: thus old entries are removed via prepare_database/clean_build;
 
wenzelm 
parents: 
77660 
diff
changeset
 | 
584  | 
Task(name, split_lines(deps), JSON.Object.parse(info), build_uuid)  | 
| 77552 | 585  | 
})  | 
| 77372 | 586  | 
|
| 78553 | 587  | 
def update_pending(  | 
588  | 
db: SQL.Database,  | 
|
589  | 
pending: State.Pending,  | 
|
590  | 
old_pending: State.Pending  | 
|
591  | 
    ): Boolean = {
 | 
|
| 77372 | 592  | 
val (delete, insert) = Library.symmetric_difference(old_pending, pending)  | 
593  | 
||
594  | 
      if (delete.nonEmpty) {
 | 
|
| 77540 | 595  | 
db.execute_statement(  | 
| 77662 | 596  | 
Pending.table.delete(sql = Generic.sql_where(names = delete.map(_.name))))  | 
| 77372 | 597  | 
}  | 
598  | 
||
| 
78552
 
384adc74e27d
performance tuning: avoid multiple db roundtrips;
 
wenzelm 
parents: 
78546 
diff
changeset
 | 
599  | 
      if (insert.nonEmpty) {
 | 
| 
 
384adc74e27d
performance tuning: avoid multiple db roundtrips;
 
wenzelm 
parents: 
78546 
diff
changeset
 | 
600  | 
db.execute_batch_statement(Pending.table.insert(), batch =  | 
| 
 
384adc74e27d
performance tuning: avoid multiple db roundtrips;
 
wenzelm 
parents: 
78546 
diff
changeset
 | 
601  | 
          for (task <- insert) yield { (stmt: SQL.Statement) =>
 | 
| 
77661
 
45bd5c26cbcc
proper build_uuid for Build_Process.Task: thus old entries are removed via prepare_database/clean_build;
 
wenzelm 
parents: 
77660 
diff
changeset
 | 
602  | 
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: 
77660 
diff
changeset
 | 
603  | 
stmt.string(2) = cat_lines(task.deps)  | 
| 
 
45bd5c26cbcc
proper build_uuid for Build_Process.Task: thus old entries are removed via prepare_database/clean_build;
 
wenzelm 
parents: 
77660 
diff
changeset
 | 
604  | 
stmt.string(3) = JSON.Format(task.info)  | 
| 
 
45bd5c26cbcc
proper build_uuid for Build_Process.Task: thus old entries are removed via prepare_database/clean_build;
 
wenzelm 
parents: 
77660 
diff
changeset
 | 
605  | 
stmt.string(4) = task.build_uuid  | 
| 77541 | 606  | 
})  | 
| 77372 | 607  | 
}  | 
608  | 
||
609  | 
delete.nonEmpty || insert.nonEmpty  | 
|
610  | 
}  | 
|
611  | 
||
| 77531 | 612  | 
|
613  | 
/* running jobs */  | 
|
614  | 
||
615  | 
    object Running {
 | 
|
616  | 
val name = Generic.name.make_primary_key  | 
|
| 77587 | 617  | 
val worker_uuid = Generic.worker_uuid  | 
| 77634 | 618  | 
val build_uuid = Generic.build_uuid  | 
| 77531 | 619  | 
      val hostname = SQL.Column.string("hostname")
 | 
620  | 
      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: 
78635 
diff
changeset
 | 
621  | 
      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: 
78839 
diff
changeset
 | 
622  | 
      val start_date = SQL.Column.date("start_date")
 | 
| 77531 | 623  | 
|
| 78266 | 624  | 
val table =  | 
| 
78839
 
7799ec03b8bd
generalized node infos: allow addressing of numa node segments via relative cpus;
 
Fabian Huch <huch@in.tum.de> 
parents: 
78635 
diff
changeset
 | 
625  | 
make_table(  | 
| 
78841
 
7f61688d4e8d
added start date to build jobs, e.g., for build time estimation;
 
Fabian Huch <huch@in.tum.de> 
parents: 
78839 
diff
changeset
 | 
626  | 
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: 
78839 
diff
changeset
 | 
627  | 
name = "running")  | 
| 77531 | 628  | 
}  | 
629  | 
||
| 
77652
 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 
wenzelm 
parents: 
77651 
diff
changeset
 | 
630  | 
def read_running(db: SQL.Database): State.Running =  | 
| 77552 | 631  | 
db.execute_query_statement(  | 
632  | 
Running.table.select(sql = SQL.order_by(List(Running.name))),  | 
|
| 
77652
 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 
wenzelm 
parents: 
77651 
diff
changeset
 | 
633  | 
Map.from[String, Job],  | 
| 77552 | 634  | 
        { res =>
 | 
635  | 
val name = res.string(Running.name)  | 
|
| 77587 | 636  | 
val worker_uuid = res.string(Running.worker_uuid)  | 
| 77634 | 637  | 
val build_uuid = res.string(Running.build_uuid)  | 
| 77552 | 638  | 
val hostname = res.string(Running.hostname)  | 
639  | 
val numa_node = res.get_int(Running.numa_node)  | 
|
| 
78839
 
7799ec03b8bd
generalized node infos: allow addressing of numa node segments via relative cpus;
 
Fabian Huch <huch@in.tum.de> 
parents: 
78635 
diff
changeset
 | 
640  | 
val rel_cpus = res.string(Running.rel_cpus)  | 
| 
78841
 
7f61688d4e8d
added start date to build jobs, e.g., for build time estimation;
 
Fabian Huch <huch@in.tum.de> 
parents: 
78839 
diff
changeset
 | 
641  | 
val start_date = res.date(Running.start_date)  | 
| 
78839
 
7799ec03b8bd
generalized node infos: allow addressing of numa node segments via relative cpus;
 
Fabian Huch <huch@in.tum.de> 
parents: 
78635 
diff
changeset
 | 
642  | 
|
| 
 
7799ec03b8bd
generalized node infos: allow addressing of numa node segments via relative cpus;
 
Fabian Huch <huch@in.tum.de> 
parents: 
78635 
diff
changeset
 | 
643  | 
val node_info = Host.Node_Info(hostname, numa_node, Host.Range.from(rel_cpus))  | 
| 
78841
 
7f61688d4e8d
added start date to build jobs, e.g., for build time estimation;
 
Fabian Huch <huch@in.tum.de> 
parents: 
78839 
diff
changeset
 | 
644  | 
name -> Job(name, worker_uuid, build_uuid, node_info, start_date, None)  | 
| 77552 | 645  | 
}  | 
646  | 
)  | 
|
| 77372 | 647  | 
|
| 78553 | 648  | 
def update_running(  | 
649  | 
db: SQL.Database,  | 
|
650  | 
running: State.Running,  | 
|
651  | 
old_running: State.Running  | 
|
652  | 
    ): Boolean = {
 | 
|
653  | 
val running0 = old_running.valuesIterator.toList  | 
|
| 
78573
 
980f3cfcbc2c
more accurate treatment of state vs. serial vs. db;
 
wenzelm 
parents: 
78571 
diff
changeset
 | 
654  | 
val running1 = running.valuesIterator.toList  | 
| 
77630
 
86ef80d13544
clarified signature: avoid confusion due to object-orientation;
 
wenzelm 
parents: 
77629 
diff
changeset
 | 
655  | 
val (delete, insert) = Library.symmetric_difference(running0, running1)  | 
| 77372 | 656  | 
|
657  | 
      if (delete.nonEmpty) {
 | 
|
| 77540 | 658  | 
db.execute_statement(  | 
| 77662 | 659  | 
Running.table.delete(sql = Generic.sql_where(names = delete.map(_.name))))  | 
| 77372 | 660  | 
}  | 
661  | 
||
| 
78552
 
384adc74e27d
performance tuning: avoid multiple db roundtrips;
 
wenzelm 
parents: 
78546 
diff
changeset
 | 
662  | 
      if (insert.nonEmpty) {
 | 
| 
 
384adc74e27d
performance tuning: avoid multiple db roundtrips;
 
wenzelm 
parents: 
78546 
diff
changeset
 | 
663  | 
db.execute_batch_statement(Running.table.insert(), batch =  | 
| 
 
384adc74e27d
performance tuning: avoid multiple db roundtrips;
 
wenzelm 
parents: 
78546 
diff
changeset
 | 
664  | 
          for (job <- insert) yield { (stmt: SQL.Statement) =>
 | 
| 
77630
 
86ef80d13544
clarified signature: avoid confusion due to object-orientation;
 
wenzelm 
parents: 
77629 
diff
changeset
 | 
665  | 
stmt.string(1) = job.name  | 
| 77587 | 666  | 
stmt.string(2) = job.worker_uuid  | 
| 77634 | 667  | 
stmt.string(3) = job.build_uuid  | 
668  | 
stmt.string(4) = job.node_info.hostname  | 
|
669  | 
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: 
78635 
diff
changeset
 | 
670  | 
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: 
78839 
diff
changeset
 | 
671  | 
stmt.date(7) = job.start_date  | 
| 77541 | 672  | 
})  | 
| 77372 | 673  | 
}  | 
674  | 
||
675  | 
delete.nonEmpty || insert.nonEmpty  | 
|
676  | 
}  | 
|
677  | 
||
| 77531 | 678  | 
|
679  | 
/* job results */  | 
|
680  | 
||
681  | 
    object Results {
 | 
|
682  | 
val name = Generic.name.make_primary_key  | 
|
| 77651 | 683  | 
val worker_uuid = Generic.worker_uuid  | 
684  | 
val build_uuid = Generic.build_uuid  | 
|
| 77531 | 685  | 
      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: 
78635 
diff
changeset
 | 
686  | 
      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: 
78635 
diff
changeset
 | 
687  | 
      val rel_cpus = SQL.Column.string("rel_cpus")
 | 
| 77531 | 688  | 
      val rc = SQL.Column.int("rc")
 | 
689  | 
      val out = SQL.Column.string("out")
 | 
|
690  | 
      val err = SQL.Column.string("err")
 | 
|
691  | 
      val timing_elapsed = SQL.Column.long("timing_elapsed")
 | 
|
692  | 
      val timing_cpu = SQL.Column.long("timing_cpu")
 | 
|
693  | 
      val timing_gc = SQL.Column.long("timing_gc")
 | 
|
| 77651 | 694  | 
      val output_shasum = SQL.Column.string("output_shasum")
 | 
695  | 
      val current = SQL.Column.bool("current")
 | 
|
| 77531 | 696  | 
|
697  | 
val table =  | 
|
| 78266 | 698  | 
make_table(  | 
| 
78839
 
7799ec03b8bd
generalized node infos: allow addressing of numa node segments via relative cpus;
 
Fabian Huch <huch@in.tum.de> 
parents: 
78635 
diff
changeset
 | 
699  | 
List(name, worker_uuid, build_uuid, hostname, numa_node, rel_cpus,  | 
| 78266 | 700  | 
rc, out, err, timing_elapsed, timing_cpu, timing_gc, output_shasum, current),  | 
701  | 
name = "results")  | 
|
| 77531 | 702  | 
}  | 
703  | 
||
| 77496 | 704  | 
def read_results_domain(db: SQL.Database): Set[String] =  | 
| 77552 | 705  | 
db.execute_query_statement(  | 
706  | 
Results.table.select(List(Results.name)),  | 
|
707  | 
Set.from[String], res => res.string(Results.name))  | 
|
| 77496 | 708  | 
|
| 
77652
 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 
wenzelm 
parents: 
77651 
diff
changeset
 | 
709  | 
def read_results(db: SQL.Database, names: Iterable[String] = Nil): State.Results =  | 
| 77552 | 710  | 
db.execute_query_statement(  | 
711  | 
Results.table.select(sql = if_proper(names, Results.name.where_member(names))),  | 
|
| 77651 | 712  | 
Map.from[String, Result],  | 
| 77552 | 713  | 
        { res =>
 | 
714  | 
val name = res.string(Results.name)  | 
|
| 77651 | 715  | 
val worker_uuid = res.string(Results.worker_uuid)  | 
716  | 
val build_uuid = res.string(Results.build_uuid)  | 
|
| 77552 | 717  | 
val hostname = res.string(Results.hostname)  | 
718  | 
val numa_node = res.get_int(Results.numa_node)  | 
|
| 
78839
 
7799ec03b8bd
generalized node infos: allow addressing of numa node segments via relative cpus;
 
Fabian Huch <huch@in.tum.de> 
parents: 
78635 
diff
changeset
 | 
719  | 
val rel_cpus = res.string(Results.rel_cpus)  | 
| 
 
7799ec03b8bd
generalized node infos: allow addressing of numa node segments via relative cpus;
 
Fabian Huch <huch@in.tum.de> 
parents: 
78635 
diff
changeset
 | 
720  | 
val node_info = Host.Node_Info(hostname, numa_node, Host.Range.from(rel_cpus))  | 
| 77651 | 721  | 
|
| 77552 | 722  | 
val rc = res.int(Results.rc)  | 
723  | 
val out = res.string(Results.out)  | 
|
724  | 
val err = res.string(Results.err)  | 
|
725  | 
val timing =  | 
|
726  | 
res.timing(  | 
|
727  | 
Results.timing_elapsed,  | 
|
728  | 
Results.timing_cpu,  | 
|
729  | 
Results.timing_gc)  | 
|
730  | 
val process_result =  | 
|
731  | 
Process_Result(rc,  | 
|
732  | 
out_lines = split_lines(out),  | 
|
733  | 
err_lines = split_lines(err),  | 
|
734  | 
timing = timing)  | 
|
| 77651 | 735  | 
|
736  | 
val output_shasum = SHA1.fake_shasum(res.string(Results.output_shasum))  | 
|
737  | 
val current = res.bool(Results.current)  | 
|
738  | 
||
739  | 
name ->  | 
|
740  | 
Result(name, worker_uuid, build_uuid, node_info, process_result, output_shasum, current)  | 
|
| 77496 | 741  | 
}  | 
| 77552 | 742  | 
)  | 
| 77372 | 743  | 
|
| 78553 | 744  | 
def update_results(  | 
745  | 
db: SQL.Database,  | 
|
746  | 
results: State.Results,  | 
|
747  | 
old_results: State.Results  | 
|
748  | 
    ): Boolean = {
 | 
|
| 78267 | 749  | 
val insert =  | 
| 78553 | 750  | 
results.valuesIterator.filterNot(res => old_results.isDefinedAt(res.name)).toList  | 
| 77372 | 751  | 
|
| 
78552
 
384adc74e27d
performance tuning: avoid multiple db roundtrips;
 
wenzelm 
parents: 
78546 
diff
changeset
 | 
752  | 
      if (insert.nonEmpty) {
 | 
| 
 
384adc74e27d
performance tuning: avoid multiple db roundtrips;
 
wenzelm 
parents: 
78546 
diff
changeset
 | 
753  | 
db.execute_batch_statement(Results.table.insert(), batch =  | 
| 
 
384adc74e27d
performance tuning: avoid multiple db roundtrips;
 
wenzelm 
parents: 
78546 
diff
changeset
 | 
754  | 
          for (result <- insert) yield { (stmt: SQL.Statement) =>
 | 
| 
 
384adc74e27d
performance tuning: avoid multiple db roundtrips;
 
wenzelm 
parents: 
78546 
diff
changeset
 | 
755  | 
val process_result = result.process_result  | 
| 77651 | 756  | 
stmt.string(1) = result.name  | 
757  | 
stmt.string(2) = result.worker_uuid  | 
|
758  | 
stmt.string(3) = result.build_uuid  | 
|
759  | 
stmt.string(4) = result.node_info.hostname  | 
|
760  | 
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: 
78635 
diff
changeset
 | 
761  | 
stmt.string(6) = Host.Range(result.node_info.rel_cpus)  | 
| 
 
7799ec03b8bd
generalized node infos: allow addressing of numa node segments via relative cpus;
 
Fabian Huch <huch@in.tum.de> 
parents: 
78635 
diff
changeset
 | 
762  | 
stmt.int(7) = process_result.rc  | 
| 
 
7799ec03b8bd
generalized node infos: allow addressing of numa node segments via relative cpus;
 
Fabian Huch <huch@in.tum.de> 
parents: 
78635 
diff
changeset
 | 
763  | 
stmt.string(8) = cat_lines(process_result.out_lines)  | 
| 
 
7799ec03b8bd
generalized node infos: allow addressing of numa node segments via relative cpus;
 
Fabian Huch <huch@in.tum.de> 
parents: 
78635 
diff
changeset
 | 
764  | 
stmt.string(9) = cat_lines(process_result.err_lines)  | 
| 
 
7799ec03b8bd
generalized node infos: allow addressing of numa node segments via relative cpus;
 
Fabian Huch <huch@in.tum.de> 
parents: 
78635 
diff
changeset
 | 
765  | 
stmt.long(10) = process_result.timing.elapsed.ms  | 
| 
 
7799ec03b8bd
generalized node infos: allow addressing of numa node segments via relative cpus;
 
Fabian Huch <huch@in.tum.de> 
parents: 
78635 
diff
changeset
 | 
766  | 
stmt.long(11) = process_result.timing.cpu.ms  | 
| 
 
7799ec03b8bd
generalized node infos: allow addressing of numa node segments via relative cpus;
 
Fabian Huch <huch@in.tum.de> 
parents: 
78635 
diff
changeset
 | 
767  | 
stmt.long(12) = process_result.timing.gc.ms  | 
| 
 
7799ec03b8bd
generalized node infos: allow addressing of numa node segments via relative cpus;
 
Fabian Huch <huch@in.tum.de> 
parents: 
78635 
diff
changeset
 | 
768  | 
stmt.string(13) = result.output_shasum.toString  | 
| 
 
7799ec03b8bd
generalized node infos: allow addressing of numa node segments via relative cpus;
 
Fabian Huch <huch@in.tum.de> 
parents: 
78635 
diff
changeset
 | 
769  | 
stmt.bool(14) = result.current  | 
| 77541 | 770  | 
})  | 
| 77372 | 771  | 
}  | 
772  | 
||
773  | 
insert.nonEmpty  | 
|
774  | 
}  | 
|
775  | 
||
| 77531 | 776  | 
|
777  | 
/* collective operations */  | 
|
778  | 
||
| 
78187
 
2df0f3604a67
clarified signature: more explicit class SQL.Data;
 
wenzelm 
parents: 
78185 
diff
changeset
 | 
779  | 
override val tables =  | 
| 77596 | 780  | 
SQL.Tables(  | 
| 77534 | 781  | 
Base.table,  | 
782  | 
Workers.table,  | 
|
783  | 
Sessions.table,  | 
|
784  | 
Pending.table,  | 
|
785  | 
Running.table,  | 
|
| 
78174
 
cc0bd66eb498
separate host.db for independent db.transaction_lock;
 
wenzelm 
parents: 
78173 
diff
changeset
 | 
786  | 
Results.table)  | 
| 77534 | 787  | 
|
| 77658 | 788  | 
val build_uuid_tables =  | 
| 
78187
 
2df0f3604a67
clarified signature: more explicit class SQL.Data;
 
wenzelm 
parents: 
78185 
diff
changeset
 | 
789  | 
tables.filter(table =>  | 
| 77658 | 790  | 
table.columns.exists(column => column.name == Generic.build_uuid.name))  | 
791  | 
||
| 78546 | 792  | 
    def pull_database(db: SQL.Database, worker_uuid: String, state: State): State = {
 | 
| 77655 | 793  | 
val serial_db = read_serial(db)  | 
794  | 
if (serial_db == state.serial) state  | 
|
| 
77652
 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 
wenzelm 
parents: 
77651 
diff
changeset
 | 
795  | 
      else {
 | 
| 77655 | 796  | 
val serial = serial_db max state.serial  | 
| 
77652
 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 
wenzelm 
parents: 
77651 
diff
changeset
 | 
797  | 
stamp_worker(db, worker_uuid, serial)  | 
| 
 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 
wenzelm 
parents: 
77651 
diff
changeset
 | 
798  | 
|
| 
78237
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
799  | 
val sessions = state.sessions.pull(read_sessions_domain(db), read_sessions(db, _))  | 
| 
77652
 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 
wenzelm 
parents: 
77651 
diff
changeset
 | 
800  | 
val pending = read_pending(db)  | 
| 
 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 
wenzelm 
parents: 
77651 
diff
changeset
 | 
801  | 
val running = pull0(read_running(db), state.running)  | 
| 
 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 
wenzelm 
parents: 
77651 
diff
changeset
 | 
802  | 
val results = pull1(read_results_domain(db), read_results(db, _), state.results)  | 
| 
 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 
wenzelm 
parents: 
77651 
diff
changeset
 | 
803  | 
|
| 
78174
 
cc0bd66eb498
separate host.db for independent db.transaction_lock;
 
wenzelm 
parents: 
78173 
diff
changeset
 | 
804  | 
state.copy(serial = serial, sessions = sessions, pending = pending,  | 
| 
 
cc0bd66eb498
separate host.db for independent db.transaction_lock;
 
wenzelm 
parents: 
78173 
diff
changeset
 | 
805  | 
running = running, results = results)  | 
| 
77652
 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 
wenzelm 
parents: 
77651 
diff
changeset
 | 
806  | 
}  | 
| 
 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 
wenzelm 
parents: 
77651 
diff
changeset
 | 
807  | 
}  | 
| 
 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 
wenzelm 
parents: 
77651 
diff
changeset
 | 
808  | 
|
| 78553 | 809  | 
def update_database(  | 
810  | 
db: SQL.Database,  | 
|
811  | 
worker_uuid: String,  | 
|
812  | 
state: State,  | 
|
813  | 
old_state: State  | 
|
814  | 
    ): State = {
 | 
|
| 
77416
 
d88c12f22ab0
clarified scope of "serial" and "numa_index" within database;
 
wenzelm 
parents: 
77415 
diff
changeset
 | 
815  | 
val changed =  | 
| 
 
d88c12f22ab0
clarified scope of "serial" and "numa_index" within database;
 
wenzelm 
parents: 
77415 
diff
changeset
 | 
816  | 
List(  | 
| 78553 | 817  | 
update_sessions(db, state.sessions, old_state.sessions),  | 
818  | 
update_pending(db, state.pending, old_state.pending),  | 
|
819  | 
update_running(db, state.running, old_state.running),  | 
|
820  | 
update_results(db, state.results, old_state.results))  | 
|
| 77372 | 821  | 
|
| 78574 | 822  | 
val state1 = if (changed.exists(identity)) state.inc_serial else state  | 
823  | 
if (state1.serial != state.serial) stamp_worker(db, worker_uuid, state1.serial)  | 
|
| 77372 | 824  | 
|
| 78574 | 825  | 
state1  | 
| 77372 | 826  | 
}  | 
827  | 
}  | 
|
| 
78218
 
a625bfb0e549
clarified signature: more operations and options;
 
wenzelm 
parents: 
78217 
diff
changeset
 | 
828  | 
|
| 
 
a625bfb0e549
clarified signature: more operations and options;
 
wenzelm 
parents: 
78217 
diff
changeset
 | 
829  | 
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: 
78394 
diff
changeset
 | 
830  | 
    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: 
78394 
diff
changeset
 | 
831  | 
private_data.read_builds(db)  | 
| 78356 | 832  | 
}  | 
| 77396 | 833  | 
}  | 
| 77372 | 834  | 
|
835  | 
||
| 77436 | 836  | 
|
837  | 
/** main process **/  | 
|
| 
77259
 
61fc2afe4c8b
clarified signature: prefer stateful object-oriented style, to make it fit better into physical world;
 
wenzelm 
parents: 
77258 
diff
changeset
 | 
838  | 
|
| 77505 | 839  | 
class Build_Process(  | 
| 78421 | 840  | 
protected final val build_context: Build.Context,  | 
| 78372 | 841  | 
protected final val build_progress: Progress,  | 
842  | 
protected final val server: SSH.Server  | 
|
| 77505 | 843  | 
)  | 
| 77436 | 844  | 
extends AutoCloseable {
 | 
845  | 
/* context */  | 
|
846  | 
||
| 78178 | 847  | 
protected final val store: Store = build_context.store  | 
| 77530 | 848  | 
protected final val build_options: Options = store.options  | 
| 
78237
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
849  | 
protected final val build_deps: isabelle.Sessions.Deps = build_context.build_deps  | 
| 77653 | 850  | 
protected final val hostname: String = build_context.hostname  | 
| 77530 | 851  | 
protected final val build_uuid: String = build_context.build_uuid  | 
| 
78156
 
da5cc332ded3
prefer Database_Progress, which is more robust (amending afb1a19307c4);
 
wenzelm 
parents: 
78154 
diff
changeset
 | 
852  | 
|
| 
 
da5cc332ded3
prefer Database_Progress, which is more robust (amending afb1a19307c4);
 
wenzelm 
parents: 
78154 
diff
changeset
 | 
853  | 
|
| 78413 | 854  | 
/* global resources with common close() operation */  | 
| 
78156
 
da5cc332ded3
prefer Database_Progress, which is more robust (amending afb1a19307c4);
 
wenzelm 
parents: 
78154 
diff
changeset
 | 
855  | 
|
| 
78969
 
1b05c2b10c9f
finalize current sessions before generating schedule;
 
Fabian Huch <huch@in.tum.de> 
parents: 
78968 
diff
changeset
 | 
856  | 
protected val _database_server: Option[SQL.Database] =  | 
| 78372 | 857  | 
    try { store.maybe_open_database_server(server = server) }
 | 
| 78214 | 858  | 
    catch { case exn: Throwable => close(); throw exn }
 | 
859  | 
||
| 78203 | 860  | 
private val _build_database: Option[SQL.Database] =  | 
| 78234 | 861  | 
    try {
 | 
| 78372 | 862  | 
      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: 
78575 
diff
changeset
 | 
863  | 
        if (!db.is_postgresql) {
 | 
| 78893 | 864  | 
          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: 
78575 
diff
changeset
 | 
865  | 
}  | 
| 
78389
 
41e8ae87184d
clarified signature: eliminate SQL.Tables.empty to avoid confusion (see also 0bd366fad888);
 
wenzelm 
parents: 
78385 
diff
changeset
 | 
866  | 
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: 
78394 
diff
changeset
 | 
867  | 
Build_Process.private_data.transaction_lock(db,  | 
| 78356 | 868  | 
create = true,  | 
869  | 
label = "Build_Process.build_database"  | 
|
870  | 
        ) {
 | 
|
| 
78396
 
7853d9072d1b
renamed object Data to private_data, to emphasize its intended scope (but it is publicly accessible in the database);
 
wenzelm 
parents: 
78394 
diff
changeset
 | 
871  | 
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: 
78394 
diff
changeset
 | 
872  | 
if (store_tables) Store.private_data.tables.lock(db, create = true)  | 
| 78234 | 873  | 
}  | 
| 
78389
 
41e8ae87184d
clarified signature: eliminate SQL.Tables.empty to avoid confusion (see also 0bd366fad888);
 
wenzelm 
parents: 
78385 
diff
changeset
 | 
874  | 
        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: 
78394 
diff
changeset
 | 
875  | 
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: 
78394 
diff
changeset
 | 
876  | 
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: 
78385 
diff
changeset
 | 
877  | 
}  | 
| 78234 | 878  | 
db  | 
879  | 
}  | 
|
880  | 
}  | 
|
| 78214 | 881  | 
    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: 
77258 
diff
changeset
 | 
882  | 
|
| 78409 | 883  | 
  protected val build_delay: Time = {
 | 
884  | 
val option =  | 
|
885  | 
      _build_database match {
 | 
|
886  | 
case Some(db) if db.is_postgresql => "build_cluster_delay"  | 
|
887  | 
case _ => "build_delay"  | 
|
888  | 
}  | 
|
889  | 
build_options.seconds(option)  | 
|
890  | 
}  | 
|
| 
78406
 
2ece6509ad6f
clarified options: accommodate potentially slow database connection;
 
wenzelm 
parents: 
78401 
diff
changeset
 | 
891  | 
|
| 
78844
 
c7f436a63108
always use host database and make protected;
 
Fabian Huch <huch@in.tum.de> 
parents: 
78842 
diff
changeset
 | 
892  | 
protected val _host_database: SQL.Database =  | 
| 
 
c7f436a63108
always use host database and make protected;
 
Fabian Huch <huch@in.tum.de> 
parents: 
78842 
diff
changeset
 | 
893  | 
    try { store.open_build_database(path = Host.private_data.database, server = server) }
 | 
| 78214 | 894  | 
    catch { case exn: Throwable => close(); throw exn }
 | 
| 
78213
 
fd0430a7b7a4
avoid repeated open_database_server: synchronized transaction_lock;
 
wenzelm 
parents: 
78205 
diff
changeset
 | 
895  | 
|
| 
78156
 
da5cc332ded3
prefer Database_Progress, which is more robust (amending afb1a19307c4);
 
wenzelm 
parents: 
78154 
diff
changeset
 | 
896  | 
  protected val (progress, worker_uuid) = synchronized {
 | 
| 78569 | 897  | 
if (_build_database.isEmpty) (build_progress, UUID.random().toString)  | 
898  | 
    else {
 | 
|
899  | 
      try {
 | 
|
900  | 
val db = store.open_build_database(Progress.private_data.database, server = server)  | 
|
901  | 
val progress =  | 
|
902  | 
new Database_Progress(db, build_progress,  | 
|
903  | 
input_messages = build_context.master,  | 
|
904  | 
output_stopped = build_context.master,  | 
|
905  | 
hostname = hostname,  | 
|
906  | 
context_uuid = build_uuid,  | 
|
907  | 
kind = "build_process",  | 
|
908  | 
timeout = Some(build_delay))  | 
|
909  | 
(progress, progress.agent_uuid)  | 
|
910  | 
}  | 
|
911  | 
      catch { case exn: Throwable => close(); throw exn }
 | 
|
| 
78156
 
da5cc332ded3
prefer Database_Progress, which is more robust (amending afb1a19307c4);
 
wenzelm 
parents: 
78154 
diff
changeset
 | 
912  | 
}  | 
| 
 
da5cc332ded3
prefer Database_Progress, which is more robust (amending afb1a19307c4);
 
wenzelm 
parents: 
78154 
diff
changeset
 | 
913  | 
}  | 
| 77638 | 914  | 
|
| 
78156
 
da5cc332ded3
prefer Database_Progress, which is more robust (amending afb1a19307c4);
 
wenzelm 
parents: 
78154 
diff
changeset
 | 
915  | 
protected val log: Logger = Logger.make_system_log(progress, build_options)  | 
| 
 
da5cc332ded3
prefer Database_Progress, which is more robust (amending afb1a19307c4);
 
wenzelm 
parents: 
78154 
diff
changeset
 | 
916  | 
|
| 
78434
 
b4ec7ea073da
clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
 
wenzelm 
parents: 
78430 
diff
changeset
 | 
917  | 
  protected def open_build_cluster(): Build_Cluster = {
 | 
| 
 
b4ec7ea073da
clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
 
wenzelm 
parents: 
78430 
diff
changeset
 | 
918  | 
val build_cluster = Build_Cluster.make(build_context, progress = build_progress)  | 
| 
 
b4ec7ea073da
clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
 
wenzelm 
parents: 
78430 
diff
changeset
 | 
919  | 
build_cluster.open()  | 
| 
 
b4ec7ea073da
clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
 
wenzelm 
parents: 
78430 
diff
changeset
 | 
920  | 
build_cluster  | 
| 
78430
 
0461fc9d43e8
more build_cluster management: open SSH connections in parallel, but synchronously;
 
wenzelm 
parents: 
78424 
diff
changeset
 | 
921  | 
}  | 
| 
 
0461fc9d43e8
more build_cluster management: open SSH connections in parallel, but synchronously;
 
wenzelm 
parents: 
78424 
diff
changeset
 | 
922  | 
|
| 78413 | 923  | 
private val _build_cluster =  | 
924  | 
    try {
 | 
|
| 
78434
 
b4ec7ea073da
clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
 
wenzelm 
parents: 
78430 
diff
changeset
 | 
925  | 
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: 
78430 
diff
changeset
 | 
926  | 
else Build_Cluster.none  | 
| 78413 | 927  | 
}  | 
928  | 
    catch { case exn: Throwable => close(); throw exn }
 | 
|
929  | 
||
| 
78156
 
da5cc332ded3
prefer Database_Progress, which is more robust (amending afb1a19307c4);
 
wenzelm 
parents: 
78154 
diff
changeset
 | 
930  | 
  def close(): Unit = synchronized {
 | 
| 78214 | 931  | 
Option(_database_server).flatten.foreach(_.close())  | 
932  | 
Option(_build_database).flatten.foreach(_.close())  | 
|
| 
78844
 
c7f436a63108
always use host database and make protected;
 
Fabian Huch <huch@in.tum.de> 
parents: 
78842 
diff
changeset
 | 
933  | 
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: 
78430 
diff
changeset
 | 
934  | 
Option(_build_cluster).foreach(_.close())  | 
| 
78156
 
da5cc332ded3
prefer Database_Progress, which is more robust (amending afb1a19307c4);
 
wenzelm 
parents: 
78154 
diff
changeset
 | 
935  | 
    progress match {
 | 
| 78563 | 936  | 
case db_progress: Database_Progress => db_progress.exit(close = true)  | 
| 78159 | 937  | 
case _ =>  | 
| 
78156
 
da5cc332ded3
prefer Database_Progress, which is more robust (amending afb1a19307c4);
 
wenzelm 
parents: 
78154 
diff
changeset
 | 
938  | 
}  | 
| 
 
da5cc332ded3
prefer Database_Progress, which is more robust (amending afb1a19307c4);
 
wenzelm 
parents: 
78154 
diff
changeset
 | 
939  | 
}  | 
| 77436 | 940  | 
|
| 78413 | 941  | 
|
| 
77437
 
dcbf96acae27
clarified signature: do not expose global state to object-oriented variants;
 
wenzelm 
parents: 
77436 
diff
changeset
 | 
942  | 
/* global state: internal var vs. external database */  | 
| 77436 | 943  | 
|
| 
77652
 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 
wenzelm 
parents: 
77651 
diff
changeset
 | 
944  | 
private var _state: Build_Process.State = Build_Process.State()  | 
| 
77437
 
dcbf96acae27
clarified signature: do not expose global state to object-oriented variants;
 
wenzelm 
parents: 
77436 
diff
changeset
 | 
945  | 
|
| 78356 | 946  | 
protected def synchronized_database[A](label: String)(body: => A): A =  | 
947  | 
    synchronized {
 | 
|
948  | 
      _build_database match {
 | 
|
949  | 
case None => body  | 
|
950  | 
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: 
78394 
diff
changeset
 | 
951  | 
          Build_Process.private_data.transaction_lock(db, label = label) {
 | 
| 78553 | 952  | 
val old_state = Build_Process.private_data.pull_database(db, worker_uuid, _state)  | 
953  | 
_state = old_state  | 
|
| 78356 | 954  | 
val res = body  | 
| 78553 | 955  | 
_state = Build_Process.private_data.update_database(db, worker_uuid, _state, old_state)  | 
| 78356 | 956  | 
res  | 
957  | 
}  | 
|
958  | 
}  | 
|
| 
77522
 
a1d30297cd61
more complete coverage of non-final Progress methods, notably for Server.Connection_Progress;
 
wenzelm 
parents: 
77521 
diff
changeset
 | 
959  | 
}  | 
| 
 
a1d30297cd61
more complete coverage of non-final Progress methods, notably for Server.Connection_Progress;
 
wenzelm 
parents: 
77521 
diff
changeset
 | 
960  | 
|
| 77505 | 961  | 
|
| 
77437
 
dcbf96acae27
clarified signature: do not expose global state to object-oriented variants;
 
wenzelm 
parents: 
77436 
diff
changeset
 | 
962  | 
/* policy operations */  | 
| 77333 | 963  | 
|
| 
77415
 
6b928419f109
clarified signature: allow more general init, e.g. from existing database;
 
wenzelm 
parents: 
77414 
diff
changeset
 | 
964  | 
  protected def init_state(state: Build_Process.State): Build_Process.State = {
 | 
| 78374 | 965  | 
val sessions1 = state.sessions.init(build_context, _database_server, progress = build_progress)  | 
| 77496 | 966  | 
|
| 
77415
 
6b928419f109
clarified signature: allow more general init, e.g. from existing database;
 
wenzelm 
parents: 
77414 
diff
changeset
 | 
967  | 
val old_pending = state.pending.iterator.map(_.name).toSet  | 
| 
 
6b928419f109
clarified signature: allow more general init, e.g. from existing database;
 
wenzelm 
parents: 
77414 
diff
changeset
 | 
968  | 
val new_pending =  | 
| 
 
6b928419f109
clarified signature: allow more general init, e.g. from existing database;
 
wenzelm 
parents: 
77414 
diff
changeset
 | 
969  | 
List.from(  | 
| 
78237
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
970  | 
for (session <- sessions1.iterator if !old_pending(session.name))  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
971  | 
yield Build_Process.Task(session.name, session.deps, JSON.Object.empty, build_uuid))  | 
| 77496 | 972  | 
val pending1 = new_pending ::: state.pending  | 
973  | 
||
| 78571 | 974  | 
state.copy(sessions = sessions1, pending = pending1)  | 
| 
77415
 
6b928419f109
clarified signature: allow more general init, e.g. from existing database;
 
wenzelm 
parents: 
77414 
diff
changeset
 | 
975  | 
}  | 
| 
77259
 
61fc2afe4c8b
clarified signature: prefer stateful object-oriented style, to make it fit better into physical world;
 
wenzelm 
parents: 
77258 
diff
changeset
 | 
976  | 
|
| 
78394
 
761d12b043d0
proper running limit, based on this worker process;
 
wenzelm 
parents: 
78393 
diff
changeset
 | 
977  | 
  protected def next_jobs(state: Build_Process.State): List[String] = {
 | 
| 
78529
 
0e79fa88cab6
build_worker is stopped independently from master build_process;
 
wenzelm 
parents: 
78510 
diff
changeset
 | 
978  | 
    val limit = {
 | 
| 
 
0e79fa88cab6
build_worker is stopped independently from master build_process;
 
wenzelm 
parents: 
78510 
diff
changeset
 | 
979  | 
      if (progress.stopped) { if (build_context.master) Int.MaxValue else 0 }
 | 
| 
 
0e79fa88cab6
build_worker is stopped independently from master build_process;
 
wenzelm 
parents: 
78510 
diff
changeset
 | 
980  | 
else build_context.max_jobs - state.build_running.length  | 
| 
 
0e79fa88cab6
build_worker is stopped independently from master build_process;
 
wenzelm 
parents: 
78510 
diff
changeset
 | 
981  | 
}  | 
| 
79020
 
ef76705bf402
clarified ready vs. next ready;
 
Fabian Huch <huch@in.tum.de> 
parents: 
78969 
diff
changeset
 | 
982  | 
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: 
78393 
diff
changeset
 | 
983  | 
else Nil  | 
| 
 
761d12b043d0
proper running limit, based on this worker process;
 
wenzelm 
parents: 
78393 
diff
changeset
 | 
984  | 
}  | 
| 
77259
 
61fc2afe4c8b
clarified signature: prefer stateful object-oriented style, to make it fit better into physical world;
 
wenzelm 
parents: 
77258 
diff
changeset
 | 
985  | 
|
| 
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: 
78841 
diff
changeset
 | 
986  | 
  protected def next_node_info(state: Build_Process.State, session_name: String): Host.Node_Info = {
 | 
| 
 
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: 
78841 
diff
changeset
 | 
987  | 
def used_nodes: Set[Int] =  | 
| 
 
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: 
78841 
diff
changeset
 | 
988  | 
Set.from(for (job <- state.running.valuesIterator; i <- job.node_info.numa_node) yield i)  | 
| 
78844
 
c7f436a63108
always use host database and make protected;
 
Fabian Huch <huch@in.tum.de> 
parents: 
78842 
diff
changeset
 | 
989  | 
val numa_node = Host.next_numa_node(_host_database, hostname, state.numa_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: 
78841 
diff
changeset
 | 
990  | 
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: 
78841 
diff
changeset
 | 
991  | 
}  | 
| 
 
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: 
78841 
diff
changeset
 | 
992  | 
|
| 
78500
 
fc6d8a2895ca
more robust ancestor_results: avoid total existence failure after build_process has crashed elsewhere;
 
wenzelm 
parents: 
78440 
diff
changeset
 | 
993  | 
protected def start_session(  | 
| 
 
fc6d8a2895ca
more robust ancestor_results: avoid total existence failure after build_process has crashed elsewhere;
 
wenzelm 
parents: 
78440 
diff
changeset
 | 
994  | 
state: Build_Process.State,  | 
| 
 
fc6d8a2895ca
more robust ancestor_results: avoid total existence failure after build_process has crashed elsewhere;
 
wenzelm 
parents: 
78440 
diff
changeset
 | 
995  | 
session_name: String,  | 
| 
 
fc6d8a2895ca
more robust ancestor_results: avoid total existence failure after build_process has crashed elsewhere;
 
wenzelm 
parents: 
78440 
diff
changeset
 | 
996  | 
ancestor_results: List[Build_Process.Result]  | 
| 
 
fc6d8a2895ca
more robust ancestor_results: avoid total existence failure after build_process has crashed elsewhere;
 
wenzelm 
parents: 
78440 
diff
changeset
 | 
997  | 
  ): Build_Process.State = {
 | 
| 
78237
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
998  | 
val sources_shasum = state.sessions(session_name).sources_shasum  | 
| 
77467
 
e27bc7957297
more robust: proper synchronization of transition from next_job to start_session;
 
wenzelm 
parents: 
77466 
diff
changeset
 | 
999  | 
|
| 
77460
 
ccca589d7027
tuned signature: support general Build_Job instances;
 
wenzelm 
parents: 
77459 
diff
changeset
 | 
1000  | 
val input_shasum =  | 
| 77650 | 1001  | 
if (ancestor_results.isEmpty) ML_Process.bootstrap_shasum()  | 
| 
77460
 
ccca589d7027
tuned signature: support general Build_Job instances;
 
wenzelm 
parents: 
77459 
diff
changeset
 | 
1002  | 
else SHA1.flat_shasum(ancestor_results.map(_.output_shasum))  | 
| 77257 | 1003  | 
|
| 
78237
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
1004  | 
val store_heap =  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
1005  | 
build_context.build_heap || Sessions.is_pure(session_name) ||  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
1006  | 
state.sessions.iterator.exists(_.ancestors.contains(session_name))  | 
| 77469 | 1007  | 
|
1008  | 
val (current, output_shasum) =  | 
|
| 78374 | 1009  | 
store.check_output(_database_server, session_name,  | 
| 
77675
 
9e5f8f6e58a0
more thorough treatment of build prefs, guarded by system option "build_through": avoid accidental rebuild of HOL etc.;
 
wenzelm 
parents: 
77664 
diff
changeset
 | 
1010  | 
session_options = build_context.sessions_structure(session_name).options,  | 
| 
78237
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
1011  | 
sources_shasum = sources_shasum,  | 
| 77469 | 1012  | 
input_shasum = input_shasum,  | 
1013  | 
fresh_build = build_context.fresh_build,  | 
|
1014  | 
store_heap = store_heap)  | 
|
1015  | 
||
| 78195 | 1016  | 
val finished = current && ancestor_results.forall(_.current)  | 
1017  | 
val skipped = build_context.no_build  | 
|
1018  | 
val cancelled = progress.stopped || !ancestor_results.forall(_.ok)  | 
|
| 77257 | 1019  | 
|
| 
78196
 
140a6f2e3728
restore heaps from database, which takes precedence over file-system;
 
wenzelm 
parents: 
78195 
diff
changeset
 | 
1020  | 
    if (!skipped && !cancelled) {
 | 
| 
78510
 
8f45302a9ff0
more thorough ML_Heap.restore: include ancestors;                                                         prefer simultaneous ML_Heap.get_entries: just one database access for heap hierarchy;
 
wenzelm 
parents: 
78507 
diff
changeset
 | 
1021  | 
val heaps = (session_name :: ancestor_results.map(_.name)).map(store.output_heap)  | 
| 
 
8f45302a9ff0
more thorough ML_Heap.restore: include ancestors;                                                         prefer simultaneous ML_Heap.get_entries: just one database access for heap hierarchy;
 
wenzelm 
parents: 
78507 
diff
changeset
 | 
1022  | 
ML_Heap.restore(_database_server, heaps, cache = store.cache.compress)  | 
| 
78196
 
140a6f2e3728
restore heaps from database, which takes precedence over file-system;
 
wenzelm 
parents: 
78195 
diff
changeset
 | 
1023  | 
}  | 
| 
 
140a6f2e3728
restore heaps from database, which takes precedence over file-system;
 
wenzelm 
parents: 
78195 
diff
changeset
 | 
1024  | 
|
| 77651 | 1025  | 
val result_name = (session_name, worker_uuid, build_uuid)  | 
1026  | 
||
| 78195 | 1027  | 
    if (finished) {
 | 
| 
77467
 
e27bc7957297
more robust: proper synchronization of transition from next_job to start_session;
 
wenzelm 
parents: 
77466 
diff
changeset
 | 
1028  | 
state  | 
| 
 
e27bc7957297
more robust: proper synchronization of transition from next_job to start_session;
 
wenzelm 
parents: 
77466 
diff
changeset
 | 
1029  | 
.remove_pending(session_name)  | 
| 77651 | 1030  | 
.make_result(result_name, Process_Result.ok, output_shasum, current = true)  | 
| 77260 | 1031  | 
}  | 
| 78195 | 1032  | 
    else if (skipped) {
 | 
| 
77521
 
5642de4d225d
clarified signature: manage "verbose" flag via "progress";
 
wenzelm 
parents: 
77514 
diff
changeset
 | 
1033  | 
      progress.echo("Skipping " + session_name + " ...", verbose = true)
 | 
| 
77467
 
e27bc7957297
more robust: proper synchronization of transition from next_job to start_session;
 
wenzelm 
parents: 
77466 
diff
changeset
 | 
1034  | 
state.  | 
| 
 
e27bc7957297
more robust: proper synchronization of transition from next_job to start_session;
 
wenzelm 
parents: 
77466 
diff
changeset
 | 
1035  | 
remove_pending(session_name).  | 
| 77651 | 1036  | 
make_result(result_name, Process_Result.error, output_shasum)  | 
| 77260 | 1037  | 
}  | 
| 78195 | 1038  | 
    else if (cancelled) {
 | 
| 
78529
 
0e79fa88cab6
build_worker is stopped independently from master build_process;
 
wenzelm 
parents: 
78510 
diff
changeset
 | 
1039  | 
      if (build_context.master) {
 | 
| 
 
0e79fa88cab6
build_worker is stopped independently from master build_process;
 
wenzelm 
parents: 
78510 
diff
changeset
 | 
1040  | 
progress.echo(session_name + " CANCELLED")  | 
| 
 
0e79fa88cab6
build_worker is stopped independently from master build_process;
 
wenzelm 
parents: 
78510 
diff
changeset
 | 
1041  | 
state  | 
| 
 
0e79fa88cab6
build_worker is stopped independently from master build_process;
 
wenzelm 
parents: 
78510 
diff
changeset
 | 
1042  | 
.remove_pending(session_name)  | 
| 
 
0e79fa88cab6
build_worker is stopped independently from master build_process;
 
wenzelm 
parents: 
78510 
diff
changeset
 | 
1043  | 
.make_result(result_name, Process_Result.undefined, output_shasum)  | 
| 
 
0e79fa88cab6
build_worker is stopped independently from master build_process;
 
wenzelm 
parents: 
78510 
diff
changeset
 | 
1044  | 
}  | 
| 
 
0e79fa88cab6
build_worker is stopped independently from master build_process;
 
wenzelm 
parents: 
78510 
diff
changeset
 | 
1045  | 
else state  | 
| 77452 | 1046  | 
}  | 
1047  | 
    else {
 | 
|
| 
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: 
78841 
diff
changeset
 | 
1048  | 
val node_info = next_node_info(state, session_name)  | 
| 77551 | 1049  | 
|
| 78575 | 1050  | 
val print_node_info =  | 
| 
78839
 
7799ec03b8bd
generalized node infos: allow addressing of numa node segments via relative cpus;
 
Fabian Huch <huch@in.tum.de> 
parents: 
78635 
diff
changeset
 | 
1051  | 
node_info.numa_node.isDefined || node_info.rel_cpus.nonEmpty ||  | 
| 78575 | 1052  | 
_build_database.isDefined && _build_database.get.is_postgresql  | 
1053  | 
||
| 77551 | 1054  | 
progress.echo(  | 
1055  | 
(if (store_heap) "Building " else "Running ") + session_name +  | 
|
| 78575 | 1056  | 
(if (print_node_info) " (on " + node_info + ")" else "") + " ...")  | 
| 77260 | 1057  | 
|
| 
78237
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
1058  | 
val session = state.sessions(session_name)  | 
| 
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
1059  | 
|
| 
77630
 
86ef80d13544
clarified signature: avoid confusion due to object-orientation;
 
wenzelm 
parents: 
77629 
diff
changeset
 | 
1060  | 
val build =  | 
| 78372 | 1061  | 
Build_Job.start_session(build_context, session, progress, log, server,  | 
| 
78237
 
c2c59de57df9
clarified static Build_Process.Context vs. dynamic Build_Process.State;
 
wenzelm 
parents: 
78234 
diff
changeset
 | 
1062  | 
build_deps.background(session_name), sources_shasum, input_shasum, node_info, store_heap)  | 
| 
77630
 
86ef80d13544
clarified signature: avoid confusion due to object-orientation;
 
wenzelm 
parents: 
77629 
diff
changeset
 | 
1063  | 
|
| 
78841
 
7f61688d4e8d
added start date to build jobs, e.g., for build time estimation;
 
Fabian Huch <huch@in.tum.de> 
parents: 
78839 
diff
changeset
 | 
1064  | 
val job =  | 
| 
 
7f61688d4e8d
added start date to build jobs, e.g., for build time estimation;
 
Fabian Huch <huch@in.tum.de> 
parents: 
78839 
diff
changeset
 | 
1065  | 
Build_Process.Job(session_name, worker_uuid, build_uuid, node_info, Date.now(), Some(build))  | 
| 77634 | 1066  | 
|
| 
78174
 
cc0bd66eb498
separate host.db for independent db.transaction_lock;
 
wenzelm 
parents: 
78173 
diff
changeset
 | 
1067  | 
state.add_running(job)  | 
| 77260 | 1068  | 
}  | 
1069  | 
}  | 
|
| 77257 | 1070  | 
|
| 77436 | 1071  | 
|
| 
77546
 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 
wenzelm 
parents: 
77545 
diff
changeset
 | 
1072  | 
/* build process roles */  | 
| 
 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 
wenzelm 
parents: 
77545 
diff
changeset
 | 
1073  | 
|
| 77654 | 1074  | 
final def is_session_name(job_name: String): Boolean =  | 
1075  | 
!Long_Name.is_qualified(job_name)  | 
|
| 77648 | 1076  | 
|
| 78356 | 1077  | 
  protected final def start_build(): Unit = synchronized_database("Build_Process.start_build") {
 | 
| 78203 | 1078  | 
    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: 
78394 
diff
changeset
 | 
1079  | 
Build_Process.private_data.start_build(db, build_uuid, build_context.ml_platform,  | 
| 
78156
 
da5cc332ded3
prefer Database_Progress, which is more robust (amending afb1a19307c4);
 
wenzelm 
parents: 
78154 
diff
changeset
 | 
1080  | 
build_context.sessions_structure.session_prefs)  | 
| 
77546
 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 
wenzelm 
parents: 
77545 
diff
changeset
 | 
1081  | 
}  | 
| 
 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 
wenzelm 
parents: 
77545 
diff
changeset
 | 
1082  | 
}  | 
| 
 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 
wenzelm 
parents: 
77545 
diff
changeset
 | 
1083  | 
|
| 78356 | 1084  | 
  protected final def stop_build(): Unit = synchronized_database("Build_Process.stop_build") {
 | 
| 78203 | 1085  | 
    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: 
78394 
diff
changeset
 | 
1086  | 
Build_Process.private_data.stop_build(db, build_uuid)  | 
| 
77546
 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 
wenzelm 
parents: 
77545 
diff
changeset
 | 
1087  | 
}  | 
| 
 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 
wenzelm 
parents: 
77545 
diff
changeset
 | 
1088  | 
}  | 
| 
 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 
wenzelm 
parents: 
77545 
diff
changeset
 | 
1089  | 
|
| 78356 | 1090  | 
  protected final def start_worker(): Unit = synchronized_database("Build_Process.start_worker") {
 | 
| 78203 | 1091  | 
    for (db <- _build_database) {
 | 
| 
77652
 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 
wenzelm 
parents: 
77651 
diff
changeset
 | 
1092  | 
_state = _state.inc_serial  | 
| 
78396
 
7853d9072d1b
renamed object Data to private_data, to emphasize its intended scope (but it is publicly accessible in the database);
 
wenzelm 
parents: 
78394 
diff
changeset
 | 
1093  | 
Build_Process.private_data.start_worker(db, worker_uuid, build_uuid, _state.serial)  | 
| 
77546
 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 
wenzelm 
parents: 
77545 
diff
changeset
 | 
1094  | 
}  | 
| 
 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 
wenzelm 
parents: 
77545 
diff
changeset
 | 
1095  | 
}  | 
| 
 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 
wenzelm 
parents: 
77545 
diff
changeset
 | 
1096  | 
|
| 78356 | 1097  | 
  protected final def stop_worker(): Unit = synchronized_database("Build_Process.stop_worker") {
 | 
| 78203 | 1098  | 
    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: 
78394 
diff
changeset
 | 
1099  | 
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: 
77545 
diff
changeset
 | 
1100  | 
}  | 
| 
 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 
wenzelm 
parents: 
77545 
diff
changeset
 | 
1101  | 
}  | 
| 
 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 
wenzelm 
parents: 
77545 
diff
changeset
 | 
1102  | 
|
| 
 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 
wenzelm 
parents: 
77545 
diff
changeset
 | 
1103  | 
|
| 77436 | 1104  | 
/* run */  | 
| 77372 | 1105  | 
|
| 
78440
 
126a12483c67
support for Build_Cluster.Session.init (rsync + Admin/init);
 
wenzelm 
parents: 
78434 
diff
changeset
 | 
1106  | 
  def run(): Build.Results = {
 | 
| 78571 | 1107  | 
    synchronized_database("Build_Process.init") {
 | 
1108  | 
      if (build_context.master) {
 | 
|
1109  | 
_build_cluster.init()  | 
|
1110  | 
_state = init_state(_state)  | 
|
1111  | 
}  | 
|
1112  | 
_state = _state.copy(numa_nodes = Host.numa_nodes(enabled = build_context.numa_shuffling))  | 
|
| 78356 | 1113  | 
}  | 
| 
77652
 
5f706f7c624b
more thorough synchronization of internal "_state" vs. external "_database";
 
wenzelm 
parents: 
77651 
diff
changeset
 | 
1114  | 
|
| 
78529
 
0e79fa88cab6
build_worker is stopped independently from master build_process;
 
wenzelm 
parents: 
78510 
diff
changeset
 | 
1115  | 
    def finished(): Boolean = synchronized_database("Build_Process.test") {
 | 
| 
 
0e79fa88cab6
build_worker is stopped independently from master build_process;
 
wenzelm 
parents: 
78510 
diff
changeset
 | 
1116  | 
if (!build_context.master && progress.stopped) _state.build_running.isEmpty  | 
| 
 
0e79fa88cab6
build_worker is stopped independently from master build_process;
 
wenzelm 
parents: 
78510 
diff
changeset
 | 
1117  | 
else _state.pending.isEmpty  | 
| 
 
0e79fa88cab6
build_worker is stopped independently from master build_process;
 
wenzelm 
parents: 
78510 
diff
changeset
 | 
1118  | 
}  | 
| 
77400
 
f3e5b3fe230e
clarified signature: more explicit "synchronized" regions;
 
wenzelm 
parents: 
77398 
diff
changeset
 | 
1119  | 
|
| 
77437
 
dcbf96acae27
clarified signature: do not expose global state to object-oriented variants;
 
wenzelm 
parents: 
77436 
diff
changeset
 | 
1120  | 
def sleep(): Unit =  | 
| 
78406
 
2ece6509ad6f
clarified options: accommodate potentially slow database connection;
 
wenzelm 
parents: 
78401 
diff
changeset
 | 
1121  | 
      Isabelle_Thread.interrupt_handler(_ => progress.stop()) { build_delay.sleep() }
 | 
| 
77437
 
dcbf96acae27
clarified signature: do not expose global state to object-oriented variants;
 
wenzelm 
parents: 
77436 
diff
changeset
 | 
1122  | 
|
| 78585 | 1123  | 
val build_progress_warnings = Synchronized(Set.empty[String])  | 
1124  | 
def build_progress_warning(msg: String): Unit =  | 
|
1125  | 
build_progress_warnings.change(seen =>  | 
|
1126  | 
        if (seen(msg)) seen else { build_progress.echo_warning(msg); seen + msg })
 | 
|
1127  | 
||
| 
78394
 
761d12b043d0
proper running limit, based on this worker process;
 
wenzelm 
parents: 
78393 
diff
changeset
 | 
1128  | 
    def check_jobs(): Boolean = synchronized_database("Build_Process.check_jobs") {
 | 
| 
 
761d12b043d0
proper running limit, based on this worker process;
 
wenzelm 
parents: 
78393 
diff
changeset
 | 
1129  | 
val jobs = next_jobs(_state)  | 
| 
 
761d12b043d0
proper running limit, based on this worker process;
 
wenzelm 
parents: 
78393 
diff
changeset
 | 
1130  | 
      for (name <- jobs) {
 | 
| 
 
761d12b043d0
proper running limit, based on this worker process;
 
wenzelm 
parents: 
78393 
diff
changeset
 | 
1131  | 
        if (is_session_name(name)) {
 | 
| 78507 | 1132  | 
          if (build_context.sessions_structure.defined(name)) {
 | 
1133  | 
            _state.ancestor_results(name) match {
 | 
|
1134  | 
case Some(results) => _state = start_session(_state, name, results)  | 
|
1135  | 
case None =>  | 
|
| 78585 | 1136  | 
                build_progress_warning("Bad build job " + quote(name) + ": no ancestor results")
 | 
| 78507 | 1137  | 
}  | 
| 
78500
 
fc6d8a2895ca
more robust ancestor_results: avoid total existence failure after build_process has crashed elsewhere;
 
wenzelm 
parents: 
78440 
diff
changeset
 | 
1138  | 
}  | 
| 78585 | 1139  | 
          else build_progress_warning("Bad build job " + quote(name) + ": no session info")
 | 
| 
78394
 
761d12b043d0
proper running limit, based on this worker process;
 
wenzelm 
parents: 
78393 
diff
changeset
 | 
1140  | 
}  | 
| 78585 | 1141  | 
        else build_progress_warning("Bad build job " + quote(name))
 | 
| 
77467
 
e27bc7957297
more robust: proper synchronization of transition from next_job to start_session;
 
wenzelm 
parents: 
77466 
diff
changeset
 | 
1142  | 
}  | 
| 
78394
 
761d12b043d0
proper running limit, based on this worker process;
 
wenzelm 
parents: 
78393 
diff
changeset
 | 
1143  | 
jobs.nonEmpty  | 
| 
77467
 
e27bc7957297
more robust: proper synchronization of transition from next_job to start_session;
 
wenzelm 
parents: 
77466 
diff
changeset
 | 
1144  | 
}  | 
| 
 
e27bc7957297
more robust: proper synchronization of transition from next_job to start_session;
 
wenzelm 
parents: 
77466 
diff
changeset
 | 
1145  | 
|
| 77335 | 1146  | 
    if (finished()) {
 | 
1147  | 
      progress.echo_warning("Nothing to build")
 | 
|
| 
78440
 
126a12483c67
support for Build_Cluster.Session.init (rsync + Admin/init);
 
wenzelm 
parents: 
78434 
diff
changeset
 | 
1148  | 
Build.Results(build_context)  | 
| 77335 | 1149  | 
}  | 
1150  | 
    else {
 | 
|
| 
77579
 
69d3547206db
clarified signature: prefer Build_Process.Context for parameters;
 
wenzelm 
parents: 
77578 
diff
changeset
 | 
1151  | 
if (build_context.master) start_build()  | 
| 78241 | 1152  | 
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: 
78430 
diff
changeset
 | 
1153  | 
_build_cluster.start()  | 
| 
77578
 
149d48a4801b
support for "isabelle build -j0": require external workers to make progress;
 
wenzelm 
parents: 
77561 
diff
changeset
 | 
1154  | 
|
| 
78434
 
b4ec7ea073da
clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
 
wenzelm 
parents: 
78430 
diff
changeset
 | 
1155  | 
      if (build_context.master && !build_context.worker_active && _build_cluster.active()) {
 | 
| 78252 | 1156  | 
        build_progress.echo("Waiting for external workers ...")
 | 
| 
77580
 
32f9e75c92e9
clarified worker state: always maintain database content via worker_uuid;
 
wenzelm 
parents: 
77579 
diff
changeset
 | 
1157  | 
}  | 
| 
77578
 
149d48a4801b
support for "isabelle build -j0": require external workers to make progress;
 
wenzelm 
parents: 
77561 
diff
changeset
 | 
1158  | 
|
| 77538 | 1159  | 
      try {
 | 
1160  | 
        while (!finished()) {
 | 
|
| 78356 | 1161  | 
          synchronized_database("Build_Process.main") {
 | 
| 77639 | 1162  | 
if (progress.stopped) _state.stop_running()  | 
| 77310 | 1163  | 
|
| 77649 | 1164  | 
            for (job <- _state.finished_running()) {
 | 
| 
78529
 
0e79fa88cab6
build_worker is stopped independently from master build_process;
 
wenzelm 
parents: 
78510 
diff
changeset
 | 
1165  | 
              job.join_build match {
 | 
| 
 
0e79fa88cab6
build_worker is stopped independently from master build_process;
 
wenzelm 
parents: 
78510 
diff
changeset
 | 
1166  | 
case None =>  | 
| 
 
0e79fa88cab6
build_worker is stopped independently from master build_process;
 
wenzelm 
parents: 
78510 
diff
changeset
 | 
1167  | 
_state = _state.remove_running(job.name)  | 
| 78530 | 1168  | 
case Some(result) =>  | 
| 
78529
 
0e79fa88cab6
build_worker is stopped independently from master build_process;
 
wenzelm 
parents: 
78510 
diff
changeset
 | 
1169  | 
val result_name = (job.name, worker_uuid, build_uuid)  | 
| 
 
0e79fa88cab6
build_worker is stopped independently from master build_process;
 
wenzelm 
parents: 
78510 
diff
changeset
 | 
1170  | 
_state = _state.  | 
| 
 
0e79fa88cab6
build_worker is stopped independently from master build_process;
 
wenzelm 
parents: 
78510 
diff
changeset
 | 
1171  | 
remove_pending(job.name).  | 
| 
 
0e79fa88cab6
build_worker is stopped independently from master build_process;
 
wenzelm 
parents: 
78510 
diff
changeset
 | 
1172  | 
remove_running(job.name).  | 
| 78530 | 1173  | 
make_result(result_name,  | 
1174  | 
result.process_result,  | 
|
1175  | 
result.output_shasum,  | 
|
| 
78529
 
0e79fa88cab6
build_worker is stopped independently from master build_process;
 
wenzelm 
parents: 
78510 
diff
changeset
 | 
1176  | 
node_info = job.node_info)  | 
| 
 
0e79fa88cab6
build_worker is stopped independently from master build_process;
 
wenzelm 
parents: 
78510 
diff
changeset
 | 
1177  | 
}  | 
| 77538 | 1178  | 
}  | 
1179  | 
}  | 
|
1180  | 
||
| 
78394
 
761d12b043d0
proper running limit, based on this worker process;
 
wenzelm 
parents: 
78393 
diff
changeset
 | 
1181  | 
if (!check_jobs()) sleep()  | 
| 77396 | 1182  | 
}  | 
| 77310 | 1183  | 
}  | 
| 
77546
 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 
wenzelm 
parents: 
77545 
diff
changeset
 | 
1184  | 
      finally {
 | 
| 
78434
 
b4ec7ea073da
clarified signature: delegate policies to Build_Cluster implementation, potentially provided by Build.Engine via Build_Process.open_build_cluster;
 
wenzelm 
parents: 
78430 
diff
changeset
 | 
1185  | 
_build_cluster.stop()  | 
| 
77580
 
32f9e75c92e9
clarified worker state: always maintain database content via worker_uuid;
 
wenzelm 
parents: 
77579 
diff
changeset
 | 
1186  | 
stop_worker()  | 
| 
77579
 
69d3547206db
clarified signature: prefer Build_Process.Context for parameters;
 
wenzelm 
parents: 
77578 
diff
changeset
 | 
1187  | 
if (build_context.master) stop_build()  | 
| 
77546
 
9b9179cda155
clarified build process roles: "worker" vs. "build";
 
wenzelm 
parents: 
77545 
diff
changeset
 | 
1188  | 
}  | 
| 
77467
 
e27bc7957297
more robust: proper synchronization of transition from next_job to start_session;
 
wenzelm 
parents: 
77466 
diff
changeset
 | 
1189  | 
|
| 78356 | 1190  | 
      synchronized_database("Build_Process.result") {
 | 
| 
78440
 
126a12483c67
support for Build_Cluster.Session.init (rsync + Admin/init);
 
wenzelm 
parents: 
78434 
diff
changeset
 | 
1191  | 
val results = for ((name, result) <- _state.results) yield name -> result.process_result  | 
| 
 
126a12483c67
support for Build_Cluster.Session.init (rsync + Admin/init);
 
wenzelm 
parents: 
78434 
diff
changeset
 | 
1192  | 
Build.Results(build_context, results = results, other_rc = _build_cluster.rc)  | 
| 77257 | 1193  | 
}  | 
1194  | 
}  | 
|
1195  | 
}  | 
|
| 
77659
 
d7eb6a4522b8
more explicit snapshot of "_state" and "_database";
 
wenzelm 
parents: 
77658 
diff
changeset
 | 
1196  | 
|
| 
 
d7eb6a4522b8
more explicit snapshot of "_state" and "_database";
 
wenzelm 
parents: 
77658 
diff
changeset
 | 
1197  | 
|
| 
 
d7eb6a4522b8
more explicit snapshot of "_state" and "_database";
 
wenzelm 
parents: 
77658 
diff
changeset
 | 
1198  | 
/* snapshot */  | 
| 
 
d7eb6a4522b8
more explicit snapshot of "_state" and "_database";
 
wenzelm 
parents: 
77658 
diff
changeset
 | 
1199  | 
|
| 78356 | 1200  | 
  def snapshot(): Build_Process.Snapshot = synchronized_database("Build_Process.snapshot") {
 | 
| 
78156
 
da5cc332ded3
prefer Database_Progress, which is more robust (amending afb1a19307c4);
 
wenzelm 
parents: 
78154 
diff
changeset
 | 
1201  | 
val (builds, workers) =  | 
| 78203 | 1202  | 
      _build_database match {
 | 
| 
78156
 
da5cc332ded3
prefer Database_Progress, which is more robust (amending afb1a19307c4);
 
wenzelm 
parents: 
78154 
diff
changeset
 | 
1203  | 
case None => (Nil, Nil)  | 
| 
77659
 
d7eb6a4522b8
more explicit snapshot of "_state" and "_database";
 
wenzelm 
parents: 
77658 
diff
changeset
 | 
1204  | 
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: 
78394 
diff
changeset
 | 
1205  | 
(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: 
78394 
diff
changeset
 | 
1206  | 
Build_Process.private_data.read_workers(db))  | 
| 
77659
 
d7eb6a4522b8
more explicit snapshot of "_state" and "_database";
 
wenzelm 
parents: 
77658 
diff
changeset
 | 
1207  | 
}  | 
| 
 
d7eb6a4522b8
more explicit snapshot of "_state" and "_database";
 
wenzelm 
parents: 
77658 
diff
changeset
 | 
1208  | 
Build_Process.Snapshot(  | 
| 77660 | 1209  | 
builds = builds,  | 
| 
77659
 
d7eb6a4522b8
more explicit snapshot of "_state" and "_database";
 
wenzelm 
parents: 
77658 
diff
changeset
 | 
1210  | 
workers = workers,  | 
| 
 
d7eb6a4522b8
more explicit snapshot of "_state" and "_database";
 
wenzelm 
parents: 
77658 
diff
changeset
 | 
1211  | 
sessions = _state.sessions,  | 
| 
 
d7eb6a4522b8
more explicit snapshot of "_state" and "_database";
 
wenzelm 
parents: 
77658 
diff
changeset
 | 
1212  | 
pending = _state.pending,  | 
| 
 
d7eb6a4522b8
more explicit snapshot of "_state" and "_database";
 
wenzelm 
parents: 
77658 
diff
changeset
 | 
1213  | 
running = _state.running,  | 
| 
 
d7eb6a4522b8
more explicit snapshot of "_state" and "_database";
 
wenzelm 
parents: 
77658 
diff
changeset
 | 
1214  | 
results = _state.results)  | 
| 
 
d7eb6a4522b8
more explicit snapshot of "_state" and "_database";
 
wenzelm 
parents: 
77658 
diff
changeset
 | 
1215  | 
}  | 
| 
78156
 
da5cc332ded3
prefer Database_Progress, which is more robust (amending afb1a19307c4);
 
wenzelm 
parents: 
78154 
diff
changeset
 | 
1216  | 
|
| 
 
da5cc332ded3
prefer Database_Progress, which is more robust (amending afb1a19307c4);
 
wenzelm 
parents: 
78154 
diff
changeset
 | 
1217  | 
|
| 
 
da5cc332ded3
prefer Database_Progress, which is more robust (amending afb1a19307c4);
 
wenzelm 
parents: 
78154 
diff
changeset
 | 
1218  | 
/* toString */  | 
| 
 
da5cc332ded3
prefer Database_Progress, which is more robust (amending afb1a19307c4);
 
wenzelm 
parents: 
78154 
diff
changeset
 | 
1219  | 
|
| 
 
da5cc332ded3
prefer Database_Progress, which is more robust (amending afb1a19307c4);
 
wenzelm 
parents: 
78154 
diff
changeset
 | 
1220  | 
override def toString: String =  | 
| 
 
da5cc332ded3
prefer Database_Progress, which is more robust (amending afb1a19307c4);
 
wenzelm 
parents: 
78154 
diff
changeset
 | 
1221  | 
"Build_Process(worker_uuid = " + quote(worker_uuid) + ", build_uuid = " + quote(build_uuid) +  | 
| 
 
da5cc332ded3
prefer Database_Progress, which is more robust (amending afb1a19307c4);
 
wenzelm 
parents: 
78154 
diff
changeset
 | 
1222  | 
if_proper(build_context.master, ", master = true") + ")"  | 
| 77238 | 1223  | 
}  |