author | Fabian Huch <huch@in.tum.de> |
Tue, 11 Jun 2024 08:58:22 +0200 | |
changeset 80343 | 595b362ab851 |
parent 80342 | 35bee9c44e1a |
child 80344 | f05a71fa1a3f |
permissions | -rw-r--r-- |
80246 | 1 |
/* Title: Pure/Build/build_manager.scala |
2 |
Author: Fabian Huch, TU Muenchen |
|
3 |
||
4 |
Isabelle manager for automated and quasi-interactive builds, with web frontend. |
|
5 |
*/ |
|
6 |
||
7 |
package isabelle |
|
8 |
||
9 |
||
10 |
import scala.collection.mutable |
|
11 |
import scala.annotation.tailrec |
|
12 |
||
13 |
||
14 |
object Build_Manager { |
|
15 |
/* task state synchronized via db */ |
|
16 |
||
17 |
object Component { |
|
18 |
def parse(s: String): Component = |
|
19 |
space_explode('/', s) match { |
|
20 |
case name :: rev :: Nil => Component(name, rev) |
|
21 |
case _ => error("Malformed component: " + quote(s)) |
|
22 |
} |
|
23 |
||
24 |
def AFP(rev: String = "") = Component("AFP", rev) |
|
25 |
} |
|
26 |
||
27 |
case class Component(name: String, rev: String = "") { |
|
28 |
override def toString: String = name + "/" + rev |
|
29 |
} |
|
30 |
||
31 |
sealed trait Build_Config { |
|
32 |
def name: String |
|
33 |
def components: List[Component] |
|
34 |
def fresh_build: Boolean |
|
80319
f83f402bc9a4
use build_cluster in ci builds;
Fabian Huch <huch@in.tum.de>
parents:
80315
diff
changeset
|
35 |
def build_cluster: Boolean |
80246 | 36 |
def command(build_hosts: List[Build_Cluster.Host]): String |
37 |
} |
|
38 |
||
80261
e3f472221f8f
add triggers to ci jobs: on commit vs timed;
Fabian Huch <huch@in.tum.de>
parents:
80260
diff
changeset
|
39 |
object CI_Build { |
e3f472221f8f
add triggers to ci jobs: on commit vs timed;
Fabian Huch <huch@in.tum.de>
parents:
80260
diff
changeset
|
40 |
def apply(job: isabelle.CI_Build.Job): CI_Build = |
80319
f83f402bc9a4
use build_cluster in ci builds;
Fabian Huch <huch@in.tum.de>
parents:
80315
diff
changeset
|
41 |
CI_Build(job.name, job.hosts.build_cluster, job.components.map(Component(_, "default"))) |
80261
e3f472221f8f
add triggers to ci jobs: on commit vs timed;
Fabian Huch <huch@in.tum.de>
parents:
80260
diff
changeset
|
42 |
} |
e3f472221f8f
add triggers to ci jobs: on commit vs timed;
Fabian Huch <huch@in.tum.de>
parents:
80260
diff
changeset
|
43 |
|
80319
f83f402bc9a4
use build_cluster in ci builds;
Fabian Huch <huch@in.tum.de>
parents:
80315
diff
changeset
|
44 |
case class CI_Build(name: String, build_cluster: Boolean, components: List[Component]) |
f83f402bc9a4
use build_cluster in ci builds;
Fabian Huch <huch@in.tum.de>
parents:
80315
diff
changeset
|
45 |
extends Build_Config { |
80246 | 46 |
def fresh_build: Boolean = true |
80281
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
47 |
def command(build_hosts: List[Build_Cluster.Host]): String = |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
48 |
" ci_build" + |
80319
f83f402bc9a4
use build_cluster in ci builds;
Fabian Huch <huch@in.tum.de>
parents:
80315
diff
changeset
|
49 |
if_proper(build_cluster, build_hosts.map(host => " -H " + Bash.string(host.print)).mkString) + |
80281
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
50 |
" " + name |
80246 | 51 |
} |
52 |
||
53 |
object User_Build { |
|
54 |
val name: String = "user" |
|
55 |
} |
|
56 |
||
57 |
case class User_Build( |
|
58 |
afp_rev: Option[String] = None, |
|
59 |
prefs: List[Options.Spec] = Nil, |
|
60 |
requirements: Boolean = false, |
|
61 |
all_sessions: Boolean = false, |
|
62 |
base_sessions: List[String] = Nil, |
|
63 |
exclude_session_groups: List[String] = Nil, |
|
64 |
exclude_sessions: List[String] = Nil, |
|
65 |
session_groups: List[String] = Nil, |
|
66 |
sessions: List[String] = Nil, |
|
67 |
build_heap: Boolean = false, |
|
68 |
clean_build: Boolean = false, |
|
69 |
export_files: Boolean = false, |
|
70 |
fresh_build: Boolean = false, |
|
80254
6b3374d208b8
add verbose option to build_task;
Fabian Huch <huch@in.tum.de>
parents:
80252
diff
changeset
|
71 |
presentation: Boolean = false, |
6b3374d208b8
add verbose option to build_task;
Fabian Huch <huch@in.tum.de>
parents:
80252
diff
changeset
|
72 |
verbose: Boolean = false |
80246 | 73 |
) extends Build_Config { |
74 |
def name: String = User_Build.name |
|
75 |
def components: List[Component] = afp_rev.map(Component.AFP).toList |
|
80319
f83f402bc9a4
use build_cluster in ci builds;
Fabian Huch <huch@in.tum.de>
parents:
80315
diff
changeset
|
76 |
def build_cluster: Boolean = true |
80246 | 77 |
def command(build_hosts: List[Build_Cluster.Host]): String = { |
78 |
" build" + |
|
79 |
if_proper(afp_rev, " -A:") + |
|
80 |
base_sessions.map(session => " -B " + Bash.string(session)).mkString + |
|
80281
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
81 |
build_hosts.map(host => " -H " + Bash.string(host.print)).mkString + |
80246 | 82 |
if_proper(presentation, " -P:") + |
83 |
if_proper(requirements, " -R") + |
|
84 |
if_proper(all_sessions, " -a") + |
|
85 |
if_proper(build_heap, " -b") + |
|
86 |
if_proper(clean_build, " -c") + |
|
87 |
if_proper(export_files, " -e") + |
|
88 |
if_proper(fresh_build, " -f") + |
|
89 |
Options.Spec.bash_strings(prefs, bg = true) + |
|
80254
6b3374d208b8
add verbose option to build_task;
Fabian Huch <huch@in.tum.de>
parents:
80252
diff
changeset
|
90 |
if_proper(verbose, " -v") + |
80246 | 91 |
sessions.map(session => " " + Bash.string(session)).mkString |
92 |
} |
|
93 |
} |
|
94 |
||
95 |
enum Priority { case low, normal, high } |
|
96 |
||
80339 | 97 |
object Build { |
98 |
def name(kind: String, id: Long): String = kind + "/" + id |
|
99 |
} |
|
100 |
||
101 |
sealed trait Build extends Name.T |
|
80246 | 102 |
|
103 |
sealed case class Task( |
|
104 |
build_config: Build_Config, |
|
80281
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
105 |
hosts_spec: String, |
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
106 |
uuid: UUID.T = UUID.random(), |
80246 | 107 |
submit_date: Date = Date.now(), |
108 |
priority: Priority = Priority.normal, |
|
109 |
isabelle_rev: String = "" |
|
80339 | 110 |
) extends Build { |
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
111 |
def name: String = uuid.toString |
80246 | 112 |
def kind: String = build_config.name |
113 |
def components: List[Component] = build_config.components |
|
80281
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
114 |
|
80319
f83f402bc9a4
use build_cluster in ci builds;
Fabian Huch <huch@in.tum.de>
parents:
80315
diff
changeset
|
115 |
def build_cluster = build_config.build_cluster |
80281
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
116 |
def build_hosts: List[Build_Cluster.Host] = |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
117 |
Build_Cluster.Host.parse(Registry.global, hosts_spec) |
80246 | 118 |
} |
119 |
||
120 |
sealed case class Job( |
|
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
121 |
uuid: UUID.T, |
80246 | 122 |
kind: String, |
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
123 |
id: Long, |
80246 | 124 |
isabelle_rev: String, |
80281
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
125 |
build_cluster: Boolean, |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
126 |
hostnames: List[String], |
80246 | 127 |
components: List[Component], |
128 |
start_date: Date = Date.now(), |
|
129 |
cancelled: Boolean = false |
|
80339 | 130 |
) extends Build { def name: String = Build.name(kind, id) } |
80246 | 131 |
|
132 |
object Status { |
|
133 |
def from_result(result: Process_Result): Status = { |
|
134 |
if (result.ok) Status.ok |
|
135 |
else if (result.interrupted) Status.cancelled |
|
136 |
else Status.failed |
|
137 |
} |
|
138 |
} |
|
139 |
||
140 |
enum Status { case ok, cancelled, aborted, failed } |
|
141 |
||
80342
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
142 |
object Result { |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
143 |
def read_log( |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
144 |
store: Store, |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
145 |
kind: String, |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
146 |
id: Long, |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
147 |
uuid: Option[UUID.T] = None |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
148 |
): Result = { |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
149 |
val build_log_file = Build_Log.Log_File.read(store.log_file(kind, id).file) |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
150 |
val End = """^Job ended at [^,]+, with status (\w+)$""".r |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
151 |
|
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
152 |
val meta_info = build_log_file.parse_meta_info() |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
153 |
val status = |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
154 |
build_log_file.lines.last match { |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
155 |
case End(status) => Status.valueOf(status) |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
156 |
case _ => Status.aborted |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
157 |
} |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
158 |
val build_host = meta_info.get_build_host.getOrElse(error("No build host")) |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
159 |
val start_date = meta_info.get_build_start.getOrElse(error("No start date")) |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
160 |
val end_date = meta_info.get_build_end |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
161 |
val isabelle_version = meta_info.get(Build_Log.Prop.isabelle_version) |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
162 |
val afp_version = meta_info.get(Build_Log.Prop.afp_version) |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
163 |
|
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
164 |
Result(kind, id, status, uuid, build_host, start_date, end_date, isabelle_version, |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
165 |
afp_version) |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
166 |
} |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
167 |
} |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
168 |
|
80246 | 169 |
sealed case class Result( |
170 |
kind: String, |
|
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
171 |
id: Long, |
80246 | 172 |
status: Status, |
80342
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
173 |
uuid: Option[UUID.T], |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
174 |
build_host: String, |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
175 |
start_date: Date, |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
176 |
end_date: Option[Date], |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
177 |
isabelle_version: Option[String], |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
178 |
afp_version: Option[String], |
80246 | 179 |
serial: Long = 0, |
80339 | 180 |
) extends Build { def name: String = Build.name(kind, id) } |
80246 | 181 |
|
182 |
object State { |
|
183 |
def max_serial(serials: Iterable[Long]): Long = serials.maxOption.getOrElse(0L) |
|
184 |
def inc_serial(serial: Long): Long = { |
|
185 |
require(serial < Long.MaxValue, "number overflow") |
|
186 |
serial + 1 |
|
187 |
} |
|
188 |
||
80272 | 189 |
type Pending = Name.Data[Task] |
190 |
type Running = Name.Data[Job] |
|
80246 | 191 |
type Finished = Map[String, Result] |
192 |
} |
|
193 |
||
194 |
sealed case class State( |
|
195 |
serial: Long = 0, |
|
196 |
pending: State.Pending = Map.empty, |
|
197 |
running: State.Running = Map.empty, |
|
198 |
finished: State.Finished = Map.empty |
|
199 |
) { |
|
200 |
def next_serial: Long = State.inc_serial(serial) |
|
201 |
||
202 |
def add_pending(task: Task): State = copy(pending = pending + (task.name -> task)) |
|
203 |
def remove_pending(name: String): State = copy(pending = pending - name) |
|
204 |
||
205 |
def num_builds = running.size + finished.size |
|
206 |
||
80281
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
207 |
def next(build_hosts: List[Build_Cluster.Host]): Option[Task] = { |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
208 |
val cluster_running = running.values.exists(_.build_cluster) |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
209 |
val available = build_hosts.map(_.hostname).toSet - running.values.flatMap(_.hostnames).toSet |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
210 |
val ready = |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
211 |
for { |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
212 |
(_, task) <- pending |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
213 |
if !task.build_cluster || !cluster_running |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
214 |
if task.build_hosts.map(_.hostname).forall(available.contains) |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
215 |
} yield task |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
216 |
|
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
217 |
if (ready.isEmpty) None |
80246 | 218 |
else { |
80281
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
219 |
val priority = ready.map(_.priority).maxBy(_.ordinal) |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
220 |
ready.filter(_.priority == priority).toList.sortBy(_.submit_date)(Date.Ordering).headOption |
80246 | 221 |
} |
80281
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
222 |
} |
80246 | 223 |
|
224 |
def add_running(job: Job): State = copy(running = running + (job.name -> job)) |
|
225 |
def remove_running(name: String): State = copy(running = running - name) |
|
226 |
||
227 |
def add_finished(result: Result): State = copy(finished = finished + (result.name -> result)) |
|
228 |
||
229 |
lazy val kinds = ( |
|
230 |
pending.values.map(_.kind) ++ |
|
231 |
running.values.map(_.kind) ++ |
|
232 |
finished.values.map(_.kind)).toList.distinct |
|
233 |
||
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
234 |
def next_id(kind: String): Long = { |
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
235 |
val serials = get_finished(kind).map(_.id) ::: get_running(kind).map(_.id) |
80246 | 236 |
State.inc_serial(State.max_serial(serials)) |
237 |
} |
|
238 |
||
239 |
def get_running(kind: String): List[Job] = |
|
240 |
(for ((_, job) <- running if job.kind == kind) yield job).toList |
|
241 |
||
242 |
def get_finished(kind: String): List[Result] = |
|
243 |
(for ((_, result) <- finished if result.kind == kind) yield result).toList |
|
244 |
||
80339 | 245 |
def get(name: String): Option[Build] = |
80246 | 246 |
pending.get(name).orElse(running.get(name)).orElse(finished.get(name)) |
247 |
||
80339 | 248 |
def get(uuid: UUID.T): Option[Build] = |
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
249 |
pending.values.find(_.uuid == uuid).orElse( |
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
250 |
running.values.find(_.uuid == uuid)).orElse( |
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
251 |
finished.values.find(_.uuid.contains(uuid))) |
80246 | 252 |
} |
253 |
||
254 |
||
255 |
/* SQL data model */ |
|
256 |
||
257 |
object private_data extends SQL.Data("isabelle_build_manager") { |
|
258 |
/* tables */ |
|
259 |
||
260 |
override lazy val tables: SQL.Tables = |
|
261 |
SQL.Tables(State.table, Pending.table, Running.table, Finished.table) |
|
262 |
||
263 |
||
264 |
/* state */ |
|
265 |
||
266 |
object State { |
|
267 |
val serial = SQL.Column.long("serial").make_primary_key |
|
268 |
||
269 |
val table = make_table(List(serial), name = "state") |
|
270 |
} |
|
271 |
||
272 |
def read_serial(db: SQL.Database): Long = |
|
273 |
db.execute_query_statementO[Long]( |
|
274 |
State.table.select(List(State.serial.max)), |
|
275 |
_.long(State.serial)).getOrElse(0L) |
|
276 |
||
277 |
def pull_state(db: SQL.Database, state: State): State = { |
|
278 |
val serial_db = read_serial(db) |
|
279 |
if (serial_db == state.serial) state |
|
280 |
else { |
|
281 |
val serial = serial_db max state.serial |
|
282 |
||
283 |
val pending = pull_pending(db) |
|
284 |
val running = pull_running(db) |
|
285 |
val finished = pull_finished(db, state.finished) |
|
286 |
||
287 |
state.copy(serial = serial, pending = pending, running = running, finished = finished) |
|
288 |
} |
|
289 |
} |
|
290 |
||
291 |
def push_state(db: SQL.Database, old_state: State, state: State): State = { |
|
292 |
val finished = push_finished(db, state.finished) |
|
293 |
val updates = |
|
294 |
List( |
|
295 |
update_pending(db, old_state.pending, state.pending), |
|
296 |
update_running(db, old_state.running, state.running), |
|
297 |
).filter(_.defined) |
|
298 |
||
299 |
if (updates.isEmpty && finished == old_state.finished) state |
|
300 |
else { |
|
301 |
val serial = state.next_serial |
|
302 |
db.execute_statement(State.table.delete(State.serial.where_equal(old_state.serial))) |
|
303 |
db.execute_statement(State.table.insert(), body = |
|
304 |
{ (stmt: SQL.Statement) => |
|
305 |
stmt.long(1) = serial |
|
306 |
}) |
|
307 |
state.copy(serial = serial, finished = finished) |
|
308 |
} |
|
309 |
} |
|
310 |
||
311 |
||
312 |
/* pending */ |
|
313 |
||
314 |
object Pending { |
|
315 |
val kind = SQL.Column.string("kind") |
|
80281
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
316 |
val build_cluster = SQL.Column.bool("build_cluster") |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
317 |
val hosts_spec = SQL.Column.string("hosts_spec") |
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
318 |
val uuid = SQL.Column.string("uuid").make_primary_key |
80246 | 319 |
val submit_date = SQL.Column.date("submit_date") |
320 |
val priority = SQL.Column.string("priority") |
|
321 |
val isabelle_rev = SQL.Column.string("isabelle_rev") |
|
322 |
val components = SQL.Column.string("components") |
|
323 |
||
324 |
val prefs = SQL.Column.string("prefs") |
|
325 |
val requirements = SQL.Column.bool("requirements") |
|
326 |
val all_sessions = SQL.Column.bool("all_sessions") |
|
327 |
val base_sessions = SQL.Column.string("base_sessions") |
|
328 |
val exclude_session_groups = SQL.Column.string("exclude_session_groups") |
|
329 |
val exclude_sessions = SQL.Column.string("exclude_sessions") |
|
330 |
val session_groups = SQL.Column.string("session_groups") |
|
331 |
val sessions = SQL.Column.string("sessions") |
|
332 |
val build_heap = SQL.Column.bool("build_heap") |
|
333 |
val clean_build = SQL.Column.bool("clean_build") |
|
334 |
val export_files = SQL.Column.bool("export_files") |
|
335 |
val fresh_build = SQL.Column.bool("fresh_build") |
|
336 |
val presentation = SQL.Column.bool("presentation") |
|
80254
6b3374d208b8
add verbose option to build_task;
Fabian Huch <huch@in.tum.de>
parents:
80252
diff
changeset
|
337 |
val verbose = SQL.Column.bool("verbose") |
80246 | 338 |
|
339 |
val table = |
|
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
340 |
make_table(List(kind, build_cluster, hosts_spec, uuid, submit_date, priority, isabelle_rev, |
80281
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
341 |
components, prefs, requirements, all_sessions, base_sessions, exclude_session_groups, |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
342 |
exclude_sessions, session_groups, sessions, build_heap, clean_build, export_files, |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
343 |
fresh_build, presentation, verbose), |
80246 | 344 |
name = "pending") |
345 |
} |
|
346 |
||
347 |
def pull_pending(db: SQL.Database): Build_Manager.State.Pending = |
|
348 |
db.execute_query_statement(Pending.table.select(), Map.from[String, Task], get = |
|
349 |
{ res => |
|
350 |
val kind = res.string(Pending.kind) |
|
80281
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
351 |
val build_cluster = res.bool(Pending.build_cluster) |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
352 |
val hosts_spec = res.string(Pending.hosts_spec) |
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
353 |
val uuid = res.string(Pending.uuid) |
80246 | 354 |
val submit_date = res.date(Pending.submit_date) |
355 |
val priority = Priority.valueOf(res.string(Pending.priority)) |
|
356 |
val isabelle_rev = res.string(Pending.isabelle_rev) |
|
357 |
val components = space_explode(',', res.string(Pending.components)).map(Component.parse) |
|
358 |
||
359 |
val build_config = |
|
80319
f83f402bc9a4
use build_cluster in ci builds;
Fabian Huch <huch@in.tum.de>
parents:
80315
diff
changeset
|
360 |
if (kind != User_Build.name) CI_Build(kind, build_cluster, components) |
80246 | 361 |
else { |
362 |
val prefs = Options.Spec.parse(res.string(Pending.prefs)) |
|
363 |
val requirements = res.bool(Pending.requirements) |
|
364 |
val all_sessions = res.bool(Pending.all_sessions) |
|
365 |
val base_sessions = space_explode(',', res.string(Pending.base_sessions)) |
|
366 |
val exclude_session_groups = |
|
367 |
space_explode(',', res.string(Pending.exclude_session_groups)) |
|
368 |
val exclude_sessions = space_explode(',', res.string(Pending.exclude_sessions)) |
|
369 |
val session_groups = space_explode(',', res.string(Pending.session_groups)) |
|
370 |
val sessions = space_explode(',', res.string(Pending.sessions)) |
|
371 |
val build_heap = res.bool(Pending.build_heap) |
|
372 |
val clean_build = res.bool(Pending.clean_build) |
|
373 |
val export_files = res.bool(Pending.export_files) |
|
374 |
val fresh_build = res.bool(Pending.fresh_build) |
|
375 |
val presentation = res.bool(Pending.presentation) |
|
80254
6b3374d208b8
add verbose option to build_task;
Fabian Huch <huch@in.tum.de>
parents:
80252
diff
changeset
|
376 |
val verbose = res.bool(Pending.verbose) |
80246 | 377 |
|
378 |
val afp_rev = components.find(_.name == Component.AFP().name).map(_.rev) |
|
379 |
User_Build(afp_rev, prefs, requirements, all_sessions, base_sessions, |
|
380 |
exclude_session_groups, exclude_sessions, session_groups, sessions, build_heap, |
|
80254
6b3374d208b8
add verbose option to build_task;
Fabian Huch <huch@in.tum.de>
parents:
80252
diff
changeset
|
381 |
clean_build, export_files, fresh_build, presentation, verbose) |
80246 | 382 |
} |
383 |
||
80319
f83f402bc9a4
use build_cluster in ci builds;
Fabian Huch <huch@in.tum.de>
parents:
80315
diff
changeset
|
384 |
val task = |
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
385 |
Task(build_config, hosts_spec, UUID.make(uuid), submit_date, priority, isabelle_rev) |
80246 | 386 |
|
387 |
task.name -> task |
|
388 |
}) |
|
389 |
||
390 |
def update_pending( |
|
391 |
db: SQL.Database, |
|
392 |
old_pending: Build_Manager.State.Pending, |
|
393 |
pending: Build_Manager.State.Pending |
|
80274 | 394 |
): Update = { |
395 |
val update = Update.make(old_pending, pending) |
|
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
396 |
val delete = update.delete.map(old_pending(_).uuid.toString) |
80246 | 397 |
|
398 |
if (update.deletes) |
|
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
399 |
db.execute_statement(Pending.table.delete(Pending.uuid.where_member(delete))) |
80246 | 400 |
|
401 |
if (update.inserts) { |
|
402 |
db.execute_batch_statement(Pending.table.insert(), batch = |
|
403 |
for (name <- update.insert) yield { (stmt: SQL.Statement) => |
|
404 |
val task = pending(name) |
|
405 |
stmt.string(1) = task.kind |
|
80281
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
406 |
stmt.bool(2) = task.build_cluster |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
407 |
stmt.string(3) = task.hosts_spec |
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
408 |
stmt.string(4) = task.uuid.toString |
80281
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
409 |
stmt.date(5) = task.submit_date |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
410 |
stmt.string(6) = task.priority.toString |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
411 |
stmt.string(7) = task.isabelle_rev |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
412 |
stmt.string(8) = task.components.mkString(",") |
80246 | 413 |
|
414 |
def get[A](f: User_Build => A): Option[A] = |
|
415 |
task.build_config match { |
|
416 |
case user_build: User_Build => Some(f(user_build)) |
|
417 |
case _ => None |
|
418 |
} |
|
419 |
||
80281
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
420 |
stmt.string(9) = get(user_build => user_build.prefs.map(_.print).mkString(",")) |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
421 |
stmt.bool(10) = get(_.requirements) |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
422 |
stmt.bool(11) = get(_.all_sessions) |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
423 |
stmt.string(12) = get(_.base_sessions.mkString(",")) |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
424 |
stmt.string(13) = get(_.exclude_session_groups.mkString(",")) |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
425 |
stmt.string(14) = get(_.exclude_sessions.mkString(",")) |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
426 |
stmt.string(15) = get(_.session_groups.mkString(",")) |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
427 |
stmt.string(16) = get(_.sessions.mkString(",")) |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
428 |
stmt.bool(17) = get(_.build_heap) |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
429 |
stmt.bool(18) = get(_.clean_build) |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
430 |
stmt.bool(19) = get(_.export_files) |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
431 |
stmt.bool(20) = get(_.fresh_build) |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
432 |
stmt.bool(21) = get(_.presentation) |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
433 |
stmt.bool(22) = get(_.verbose) |
80246 | 434 |
}) |
435 |
} |
|
436 |
||
437 |
update |
|
438 |
} |
|
439 |
||
440 |
||
441 |
/* running */ |
|
442 |
||
443 |
object Running { |
|
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
444 |
val uuid = SQL.Column.string("uuid").make_primary_key |
80246 | 445 |
val kind = SQL.Column.string("kind") |
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
446 |
val id = SQL.Column.long("id") |
80246 | 447 |
val isabelle_rev = SQL.Column.string("isabelle_rev") |
80281
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
448 |
val build_cluster = SQL.Column.bool("build_cluster") |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
449 |
val hostnames = SQL.Column.string("hostnames") |
80246 | 450 |
val components = SQL.Column.string("components") |
451 |
val start_date = SQL.Column.date("start_date") |
|
452 |
val cancelled = SQL.Column.bool("cancelled") |
|
453 |
||
454 |
val table = |
|
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
455 |
make_table(List(uuid, kind, id, isabelle_rev, build_cluster, hostnames, components, |
80281
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
456 |
start_date, cancelled), |
80246 | 457 |
name = "running") |
458 |
} |
|
459 |
||
460 |
def pull_running(db: SQL.Database): Build_Manager.State.Running = |
|
461 |
db.execute_query_statement(Running.table.select(), Map.from[String, Job], get = |
|
462 |
{ res => |
|
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
463 |
val uuid = res.string(Running.uuid) |
80246 | 464 |
val kind = res.string(Running.kind) |
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
465 |
val id = res.long(Running.id) |
80246 | 466 |
val isabelle_rev = res.string(Running.isabelle_rev) |
80281
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
467 |
val build_cluster = res.bool(Running.build_cluster) |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
468 |
val hostnames = space_explode(',', res.string(Running.hostnames)) |
80246 | 469 |
val components = space_explode(',', res.string(Running.components)).map(Component.parse) |
470 |
val start_date = res.date(Running.start_date) |
|
471 |
val cancelled = res.bool(Running.cancelled) |
|
472 |
||
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
473 |
val job = Job(UUID.make(uuid), kind, id, isabelle_rev, build_cluster, hostnames, |
80281
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
474 |
components, start_date, cancelled) |
80246 | 475 |
|
476 |
job.name -> job |
|
477 |
}) |
|
478 |
||
479 |
def update_running( |
|
480 |
db: SQL.Database, |
|
481 |
old_running: Build_Manager.State.Running, |
|
482 |
running: Build_Manager.State.Running |
|
80274 | 483 |
): Update = { |
484 |
val update = Update.make(old_running, running) |
|
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
485 |
val delete = update.delete.map(old_running(_).uuid.toString) |
80246 | 486 |
|
487 |
if (update.deletes) |
|
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
488 |
db.execute_statement(Running.table.delete(Running.uuid.where_member(delete))) |
80246 | 489 |
|
490 |
if (update.inserts) { |
|
491 |
db.execute_batch_statement(Running.table.insert(), batch = |
|
492 |
for (name <- update.insert) yield { (stmt: SQL.Statement) => |
|
493 |
val job = running(name) |
|
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
494 |
stmt.string(1) = job.uuid.toString |
80246 | 495 |
stmt.string(2) = job.kind |
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
496 |
stmt.long(3) = job.id |
80246 | 497 |
stmt.string(4) = job.isabelle_rev |
80281
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
498 |
stmt.bool(5) = job.build_cluster |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
499 |
stmt.string(6) = job.hostnames.mkString(",") |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
500 |
stmt.string(7) = job.components.mkString(",") |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
501 |
stmt.date(8) = job.start_date |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
502 |
stmt.bool(9) = job.cancelled |
80246 | 503 |
}) |
504 |
} |
|
505 |
update |
|
506 |
} |
|
507 |
||
508 |
||
509 |
/* finished */ |
|
510 |
||
511 |
object Finished { |
|
512 |
val kind = SQL.Column.string("kind") |
|
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
513 |
val id = SQL.Column.long("id") |
80246 | 514 |
val status = SQL.Column.string("status") |
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
515 |
val uuid = SQL.Column.string("uuid") |
80342
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
516 |
val build_host = SQL.Column.string("build_host") |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
517 |
val start_date = SQL.Column.date("start_date") |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
518 |
val end_date = SQL.Column.date("end_date") |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
519 |
val isabelle_version = SQL.Column.string("isabelle_version") |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
520 |
val afp_version = SQL.Column.string("afp_version") |
80246 | 521 |
val serial = SQL.Column.long("serial").make_primary_key |
522 |
||
80342
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
523 |
val table = |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
524 |
make_table( |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
525 |
List(kind, id, status, uuid, build_host, start_date, end_date, isabelle_version, |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
526 |
afp_version, serial), |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
527 |
name = "finished") |
80246 | 528 |
} |
529 |
||
530 |
def read_finished_serial(db: SQL.Database): Long = |
|
531 |
db.execute_query_statementO[Long]( |
|
532 |
Finished.table.select(List(Finished.serial.max)), |
|
533 |
_.long(Finished.serial)).getOrElse(0L) |
|
534 |
||
535 |
def pull_finished( |
|
536 |
db: SQL.Database, |
|
537 |
finished: Build_Manager.State.Finished |
|
538 |
): Build_Manager.State.Finished = { |
|
539 |
val max_serial0 = Build_Manager.State.max_serial(finished.values.map(_.serial)) |
|
540 |
val max_serial1 = read_finished_serial(db) |
|
541 |
val missing = (max_serial0 + 1) to max_serial1 |
|
542 |
finished ++ db.execute_query_statement( |
|
543 |
Finished.table.select(sql = Finished.serial.where_member_long(missing)), |
|
544 |
Map.from[String, Result], get = |
|
545 |
{ res => |
|
546 |
val kind = res.string(Finished.kind) |
|
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
547 |
val id = res.long(Finished.id) |
80246 | 548 |
val status = Status.valueOf(res.string(Finished.status)) |
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
549 |
val uuid = res.get_string(Finished.uuid).map(UUID.make) |
80342
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
550 |
val build_host = res.string(Finished.build_host) |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
551 |
val start_date = res.date(Finished.start_date) |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
552 |
val end_date = res.get_date(Finished.end_date) |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
553 |
val isabelle_version = res.get_string(Finished.isabelle_version) |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
554 |
val afp_version = res.get_string(Finished.afp_version) |
80246 | 555 |
val serial = res.long(Finished.serial) |
556 |
||
80342
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
557 |
val result = Result(kind, id, status, uuid, build_host, start_date, end_date, |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
558 |
isabelle_version, afp_version, serial) |
80246 | 559 |
result.name -> result |
560 |
} |
|
561 |
) |
|
562 |
} |
|
563 |
||
564 |
def push_finished( |
|
565 |
db: SQL.Database, |
|
566 |
finished: Build_Manager.State.Finished |
|
567 |
): Build_Manager.State.Finished = { |
|
568 |
val (insert0, old) = finished.partition(_._2.serial == 0L) |
|
569 |
val max_serial = Build_Manager.State.max_serial(finished.map(_._2.serial)) |
|
570 |
val insert = |
|
571 |
for (((_, result), n) <- insert0.zipWithIndex) |
|
572 |
yield result.copy(serial = max_serial + 1 + n) |
|
573 |
||
574 |
if (insert.nonEmpty) |
|
575 |
db.execute_batch_statement(Finished.table.insert(), batch = |
|
576 |
for (result <- insert) yield { (stmt: SQL.Statement) => |
|
577 |
stmt.string(1) = result.kind |
|
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
578 |
stmt.long(2) = result.id |
80246 | 579 |
stmt.string(3) = result.status.toString |
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
580 |
stmt.string(4) = result.uuid.map(_.toString) |
80342
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
581 |
stmt.string(5) = result.build_host |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
582 |
stmt.date(6) = result.start_date |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
583 |
stmt.date(7) = result.end_date |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
584 |
stmt.string(8) = result.isabelle_version |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
585 |
stmt.string(9) = result.afp_version |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
586 |
stmt.long(10) = result.serial |
80246 | 587 |
}) |
588 |
||
589 |
old ++ insert.map(result => result.serial.toString -> result) |
|
590 |
} |
|
591 |
} |
|
592 |
||
593 |
||
594 |
/* running build manager processes */ |
|
595 |
||
596 |
abstract class Loop_Process[A](name: String, store: Store, progress: Progress) |
|
597 |
extends Runnable { |
|
598 |
val options = store.options |
|
599 |
||
600 |
private val _database = |
|
601 |
try { store.open_database() } |
|
602 |
catch { case exn: Throwable => close(); throw exn } |
|
603 |
||
604 |
def close(): Unit = Option(_database).foreach(_.close()) |
|
605 |
||
606 |
protected var _state = State() |
|
607 |
||
608 |
protected def synchronized_database[A](label: String)(body: => A): A = synchronized { |
|
609 |
Build_Manager.private_data.transaction_lock(_database, label = name + "." + label) { |
|
610 |
val old_state = Build_Manager.private_data.pull_state(_database, _state) |
|
611 |
_state = old_state |
|
612 |
val res = body |
|
613 |
_state = Build_Manager.private_data.push_state(_database, old_state, _state) |
|
614 |
res |
|
615 |
} |
|
616 |
} |
|
617 |
||
618 |
protected def delay = options.seconds("build_manager_delay") |
|
619 |
||
620 |
def init: A |
|
621 |
def loop_body(a: A): A |
|
622 |
def stopped(a: A): Boolean = progress.stopped |
|
623 |
||
624 |
private val interrupted = Synchronized(false) |
|
625 |
private def sleep(time_limit: Time): Unit = |
|
626 |
interrupted.timed_access(_ => Some(time_limit), b => if (b) Some((), false) else None) |
|
627 |
def interrupt(): Unit = interrupted.change(_ => true) |
|
628 |
||
629 |
@tailrec private def loop(a: A): Unit = |
|
630 |
if (!stopped(a)) { |
|
631 |
val start = Time.now() |
|
632 |
val a1 = loop_body(a) |
|
633 |
if (!stopped(a)) { |
|
634 |
sleep(start + delay) |
|
635 |
loop(a1) |
|
636 |
} |
|
637 |
} |
|
638 |
||
639 |
override def run(): Unit = { |
|
640 |
progress.echo("Started " + name) |
|
641 |
loop(init) |
|
642 |
close() |
|
643 |
progress.echo("Stopped " + name) |
|
644 |
} |
|
645 |
||
646 |
def echo(msg: String) = progress.echo(name + ": " + msg) |
|
647 |
def echo_error_message(msg: String) = progress.echo_error_message(name + ": " + msg) |
|
648 |
} |
|
649 |
||
650 |
||
651 |
/* build runner */ |
|
652 |
||
653 |
object Runner { |
|
654 |
object State { |
|
655 |
def empty: State = new State(Map.empty, Map.empty) |
|
656 |
} |
|
657 |
||
658 |
class State private( |
|
80279
02424b81472a
clarified: add explicit build process;
Fabian Huch <huch@in.tum.de>
parents:
80278
diff
changeset
|
659 |
process_futures: Map[String, Future[Build_Process]], |
80277 | 660 |
result_futures: Map[String, Future[Process_Result]] |
80246 | 661 |
) { |
80277 | 662 |
def is_empty = process_futures.isEmpty && result_futures.isEmpty |
80246 | 663 |
|
80280
7987b33fb6c5
clarified context: operations now in build process;
Fabian Huch <huch@in.tum.de>
parents:
80279
diff
changeset
|
664 |
def init(context: Context): State = { |
7987b33fb6c5
clarified context: operations now in build process;
Fabian Huch <huch@in.tum.de>
parents:
80279
diff
changeset
|
665 |
val process_future = Future.fork(Build_Process.open(context)) |
80277 | 666 |
val result_future = |
80246 | 667 |
Future.fork( |
80277 | 668 |
process_future.join_result match { |
80279
02424b81472a
clarified: add explicit build process;
Fabian Huch <huch@in.tum.de>
parents:
80278
diff
changeset
|
669 |
case Exn.Res(process) => process.run() |
80284
7a5bbc2e4bad
build manager: echo error messages to server output;
Fabian Huch <huch@in.tum.de>
parents:
80283
diff
changeset
|
670 |
case Exn.Exn(exn) => Process_Result(Process_Result.RC.interrupt).error(exn.getMessage) |
80246 | 671 |
}) |
80277 | 672 |
new State( |
80280
7987b33fb6c5
clarified context: operations now in build process;
Fabian Huch <huch@in.tum.de>
parents:
80279
diff
changeset
|
673 |
process_futures + (context.name -> process_future), |
7987b33fb6c5
clarified context: operations now in build process;
Fabian Huch <huch@in.tum.de>
parents:
80279
diff
changeset
|
674 |
result_futures + (context.name -> result_future)) |
80246 | 675 |
} |
676 |
||
80277 | 677 |
def running: List[String] = process_futures.keys.toList |
80246 | 678 |
|
679 |
def update: (State, Map[String, Process_Result]) = { |
|
680 |
val finished = |
|
80282
3c3a9154c107
always handle interrupted jobs;
Fabian Huch <huch@in.tum.de>
parents:
80281
diff
changeset
|
681 |
for ((name, future) <- result_futures if future.is_finished) |
3c3a9154c107
always handle interrupted jobs;
Fabian Huch <huch@in.tum.de>
parents:
80281
diff
changeset
|
682 |
yield name -> |
3c3a9154c107
always handle interrupted jobs;
Fabian Huch <huch@in.tum.de>
parents:
80281
diff
changeset
|
683 |
(future.join_result match { |
3c3a9154c107
always handle interrupted jobs;
Fabian Huch <huch@in.tum.de>
parents:
80281
diff
changeset
|
684 |
case Exn.Res(result) => result |
80284
7a5bbc2e4bad
build manager: echo error messages to server output;
Fabian Huch <huch@in.tum.de>
parents:
80283
diff
changeset
|
685 |
case Exn.Exn(exn) => Process_Result(Process_Result.RC.interrupt).error(exn.getMessage) |
80282
3c3a9154c107
always handle interrupted jobs;
Fabian Huch <huch@in.tum.de>
parents:
80281
diff
changeset
|
686 |
}) |
80246 | 687 |
|
80277 | 688 |
val process_futures1 = process_futures.filterNot((name, _) => finished.contains(name)) |
689 |
val result_futures1 = result_futures.filterNot((name, _) => finished.contains(name)) |
|
80246 | 690 |
|
80277 | 691 |
(new State(process_futures1, result_futures1), finished) |
80246 | 692 |
} |
693 |
||
694 |
def cancel(cancelled: List[String]): State = { |
|
695 |
for (name <- cancelled) { |
|
80277 | 696 |
val process_future = process_futures(name) |
80279
02424b81472a
clarified: add explicit build process;
Fabian Huch <huch@in.tum.de>
parents:
80278
diff
changeset
|
697 |
if (process_future.is_finished) process_future.join.cancel() |
80277 | 698 |
else process_future.cancel() |
80246 | 699 |
} |
700 |
||
80277 | 701 |
new State(process_futures.filterNot((name, _) => cancelled.contains(name)), result_futures) |
80246 | 702 |
} |
703 |
} |
|
704 |
} |
|
705 |
||
706 |
class Runner( |
|
707 |
store: Store, |
|
708 |
build_hosts: List[Build_Cluster.Host], |
|
709 |
isabelle_repository: Mercurial.Repository, |
|
710 |
sync_dirs: List[Sync.Dir], |
|
711 |
progress: Progress |
|
712 |
) extends Loop_Process[Runner.State]("Runner", store, progress) { |
|
713 |
val rsync_context = Rsync.Context() |
|
714 |
||
715 |
private def sync(repository: Mercurial.Repository, rev: String, target: Path): String = { |
|
716 |
repository.pull() |
|
717 |
||
718 |
if (rev.nonEmpty) repository.sync(rsync_context, target, rev = rev) |
|
719 |
||
720 |
Exn.capture(repository.id(File.read(target + Mercurial.Hg_Sync.PATH_ID))) match { |
|
721 |
case Exn.Res(res) => res |
|
722 |
case Exn.Exn(exn) => "" |
|
723 |
} |
|
724 |
} |
|
725 |
||
80280
7987b33fb6c5
clarified context: operations now in build process;
Fabian Huch <huch@in.tum.de>
parents:
80279
diff
changeset
|
726 |
private def start_next(): Option[Context] = |
7987b33fb6c5
clarified context: operations now in build process;
Fabian Huch <huch@in.tum.de>
parents:
80279
diff
changeset
|
727 |
synchronized_database("start_next") { |
80281
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
728 |
_state.next(build_hosts).flatMap { task => |
80340
992bd899a027
improve build manager log (for build_log);
Fabian Huch <huch@in.tum.de>
parents:
80339
diff
changeset
|
729 |
echo("Initializing " + task.name) |
80246 | 730 |
|
731 |
_state = _state.remove_pending(task.name) |
|
732 |
||
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
733 |
val id = _state.next_id(task.kind) |
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
734 |
val context = Context(store, task, id) |
80246 | 735 |
|
80340
992bd899a027
improve build manager log (for build_log);
Fabian Huch <huch@in.tum.de>
parents:
80339
diff
changeset
|
736 |
val start_date = Date.now() |
992bd899a027
improve build manager log (for build_log);
Fabian Huch <huch@in.tum.de>
parents:
80339
diff
changeset
|
737 |
|
992bd899a027
improve build manager log (for build_log);
Fabian Huch <huch@in.tum.de>
parents:
80339
diff
changeset
|
738 |
val start_msg = |
992bd899a027
improve build manager log (for build_log);
Fabian Huch <huch@in.tum.de>
parents:
80339
diff
changeset
|
739 |
"Starting job " + Build.name(task.kind, id) + |
992bd899a027
improve build manager log (for build_log);
Fabian Huch <huch@in.tum.de>
parents:
80339
diff
changeset
|
740 |
" at " + Build_Log.print_date(start_date) + "," + |
992bd899a027
improve build manager log (for build_log);
Fabian Huch <huch@in.tum.de>
parents:
80339
diff
changeset
|
741 |
" on " + ( |
992bd899a027
improve build manager log (for build_log);
Fabian Huch <huch@in.tum.de>
parents:
80339
diff
changeset
|
742 |
if (task.build_cluster) "cluster" |
992bd899a027
improve build manager log (for build_log);
Fabian Huch <huch@in.tum.de>
parents:
80339
diff
changeset
|
743 |
else Library.the_single(task.build_hosts).hostname) |
992bd899a027
improve build manager log (for build_log);
Fabian Huch <huch@in.tum.de>
parents:
80339
diff
changeset
|
744 |
|
992bd899a027
improve build manager log (for build_log);
Fabian Huch <huch@in.tum.de>
parents:
80339
diff
changeset
|
745 |
echo(start_msg + " (id " + task.uuid + ")") |
992bd899a027
improve build manager log (for build_log);
Fabian Huch <huch@in.tum.de>
parents:
80339
diff
changeset
|
746 |
|
80246 | 747 |
Exn.capture { |
80280
7987b33fb6c5
clarified context: operations now in build process;
Fabian Huch <huch@in.tum.de>
parents:
80279
diff
changeset
|
748 |
context.init() |
80340
992bd899a027
improve build manager log (for build_log);
Fabian Huch <huch@in.tum.de>
parents:
80339
diff
changeset
|
749 |
context.progress.echo(start_msg) |
992bd899a027
improve build manager log (for build_log);
Fabian Huch <huch@in.tum.de>
parents:
80339
diff
changeset
|
750 |
|
80280
7987b33fb6c5
clarified context: operations now in build process;
Fabian Huch <huch@in.tum.de>
parents:
80279
diff
changeset
|
751 |
store.sync_permissions(context.task_dir) |
80255
1844c169e360
ensure permissions when starting build task (e.g., due to misconfigured client);
Fabian Huch <huch@in.tum.de>
parents:
80254
diff
changeset
|
752 |
|
80246 | 753 |
val isabelle_rev = |
80280
7987b33fb6c5
clarified context: operations now in build process;
Fabian Huch <huch@in.tum.de>
parents:
80279
diff
changeset
|
754 |
sync(isabelle_repository, task.isabelle_rev, context.task_dir) |
80246 | 755 |
|
80281
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
756 |
val hostnames = task.build_hosts.map(_.hostname).distinct |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
757 |
|
80246 | 758 |
val components = |
759 |
for (component <- task.components) |
|
760 |
yield sync_dirs.find(_.name == component.name) match { |
|
761 |
case Some(sync_dir) => |
|
80280
7987b33fb6c5
clarified context: operations now in build process;
Fabian Huch <huch@in.tum.de>
parents:
80279
diff
changeset
|
762 |
val target = context.task_dir + sync_dir.target |
80246 | 763 |
component.copy(rev = sync(sync_dir.hg, component.rev, target)) |
764 |
case None => |
|
765 |
if (component.rev.isEmpty) component |
|
766 |
else error("Unknown component " + component) |
|
767 |
} |
|
768 |
||
80340
992bd899a027
improve build manager log (for build_log);
Fabian Huch <huch@in.tum.de>
parents:
80339
diff
changeset
|
769 |
Job(task.uuid, task.kind, id, isabelle_rev, task.build_cluster, hostnames, components, |
992bd899a027
improve build manager log (for build_log);
Fabian Huch <huch@in.tum.de>
parents:
80339
diff
changeset
|
770 |
start_date) |
80246 | 771 |
} match { |
772 |
case Exn.Res(job) => |
|
773 |
_state = _state.add_running(job) |
|
774 |
||
80340
992bd899a027
improve build manager log (for build_log);
Fabian Huch <huch@in.tum.de>
parents:
80339
diff
changeset
|
775 |
for { |
992bd899a027
improve build manager log (for build_log);
Fabian Huch <huch@in.tum.de>
parents:
80339
diff
changeset
|
776 |
component <- Component("Isabelle", job.isabelle_rev) :: job.components |
992bd899a027
improve build manager log (for build_log);
Fabian Huch <huch@in.tum.de>
parents:
80339
diff
changeset
|
777 |
if component.rev.nonEmpty |
992bd899a027
improve build manager log (for build_log);
Fabian Huch <huch@in.tum.de>
parents:
80339
diff
changeset
|
778 |
} context.progress.echo("Using " + component.toString) |
80246 | 779 |
|
80280
7987b33fb6c5
clarified context: operations now in build process;
Fabian Huch <huch@in.tum.de>
parents:
80279
diff
changeset
|
780 |
Some(context) |
80246 | 781 |
case Exn.Exn(exn) => |
80340
992bd899a027
improve build manager log (for build_log);
Fabian Huch <huch@in.tum.de>
parents:
80339
diff
changeset
|
782 |
context.progress.echo_error_message("Failed to start job: " + exn.getMessage) |
992bd899a027
improve build manager log (for build_log);
Fabian Huch <huch@in.tum.de>
parents:
80339
diff
changeset
|
783 |
echo_error_message("Failed to start " + task.uuid + ": " + exn.getMessage) |
80246 | 784 |
|
80280
7987b33fb6c5
clarified context: operations now in build process;
Fabian Huch <huch@in.tum.de>
parents:
80279
diff
changeset
|
785 |
Isabelle_System.rm_tree(context.task_dir) |
80246 | 786 |
|
80342
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
787 |
_state = _state.add_finished(Result.read_log(store, task.kind, id, Some(task.uuid))) |
80340
992bd899a027
improve build manager log (for build_log);
Fabian Huch <huch@in.tum.de>
parents:
80339
diff
changeset
|
788 |
|
80246 | 789 |
None |
790 |
} |
|
791 |
} |
|
792 |
} |
|
793 |
||
794 |
private def stop_cancelled(state: Runner.State): Runner.State = |
|
795 |
synchronized_database("stop_cancelled") { |
|
796 |
val cancelled = for (name <- state.running if _state.running(name).cancelled) yield name |
|
797 |
state.cancel(cancelled) |
|
798 |
} |
|
799 |
||
800 |
private def finish_job(name: String, process_result: Process_Result): Unit = |
|
801 |
synchronized_database("finish_job") { |
|
802 |
val job = _state.running(name) |
|
803 |
||
80342
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
804 |
val end_date = Date.now() |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
805 |
val status = Status.from_result(process_result) |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
806 |
val end_msg = "Job ended at " + Build_Log.print_date(end_date) + ", with status " + status |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
807 |
|
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
808 |
new File_Progress(store.log_file(job.kind, job.id)).echo(end_msg) |
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
809 |
val result = Result.read_log(store, job.kind, job.id, Some(job.uuid)) |
80340
992bd899a027
improve build manager log (for build_log);
Fabian Huch <huch@in.tum.de>
parents:
80339
diff
changeset
|
810 |
|
80284
7a5bbc2e4bad
build manager: echo error messages to server output;
Fabian Huch <huch@in.tum.de>
parents:
80283
diff
changeset
|
811 |
val interrupted_error = process_result.interrupted && process_result.err.nonEmpty |
7a5bbc2e4bad
build manager: echo error messages to server output;
Fabian Huch <huch@in.tum.de>
parents:
80283
diff
changeset
|
812 |
val err_msg = if_proper(interrupted_error, ": " + process_result.err) |
80340
992bd899a027
improve build manager log (for build_log);
Fabian Huch <huch@in.tum.de>
parents:
80339
diff
changeset
|
813 |
echo(end_msg + " (code " + process_result.rc + ")" + err_msg) |
80246 | 814 |
|
815 |
_state = _state |
|
816 |
.remove_running(job.name) |
|
817 |
.add_finished(result) |
|
818 |
} |
|
819 |
||
820 |
override def stopped(state: Runner.State): Boolean = progress.stopped && state.is_empty |
|
821 |
||
822 |
def init: Runner.State = Runner.State.empty |
|
823 |
def loop_body(state: Runner.State): Runner.State = { |
|
80281
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
824 |
val state1 = |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
825 |
if (progress.stopped) state |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
826 |
else { |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
827 |
start_next() match { |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
828 |
case None => state |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
829 |
case Some(context) => state.init(context) |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
830 |
} |
80246 | 831 |
} |
80281
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
832 |
val state2 = stop_cancelled(state1) |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
833 |
val (state3, results) = state2.update |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
834 |
results.foreach(finish_job) |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
835 |
state3 |
80246 | 836 |
} |
837 |
} |
|
838 |
||
839 |
||
840 |
/* repository poller */ |
|
841 |
||
842 |
object Poller { |
|
80260
ed9b1598d293
manage components of ci builds;
Fabian Huch <huch@in.tum.de>
parents:
80259
diff
changeset
|
843 |
case class Versions(isabelle: String, components: List[Component]) |
ed9b1598d293
manage components of ci builds;
Fabian Huch <huch@in.tum.de>
parents:
80259
diff
changeset
|
844 |
case class State(current: Versions, next: Future[Versions]) |
80246 | 845 |
} |
846 |
||
847 |
class Poller( |
|
80260
ed9b1598d293
manage components of ci builds;
Fabian Huch <huch@in.tum.de>
parents:
80259
diff
changeset
|
848 |
ci_jobs: List[isabelle.CI_Build.Job], |
80246 | 849 |
store: Store, |
850 |
isabelle_repository: Mercurial.Repository, |
|
851 |
sync_dirs: List[Sync.Dir], |
|
852 |
progress: Progress |
|
853 |
) extends Loop_Process[Poller.State]("Poller", store, progress) { |
|
854 |
||
855 |
override def delay = options.seconds("build_manager_poll_delay") |
|
856 |
||
80260
ed9b1598d293
manage components of ci builds;
Fabian Huch <huch@in.tum.de>
parents:
80259
diff
changeset
|
857 |
private def current: Poller.Versions = |
ed9b1598d293
manage components of ci builds;
Fabian Huch <huch@in.tum.de>
parents:
80259
diff
changeset
|
858 |
Poller.Versions(isabelle_repository.id("default"), sync_dirs.map(dir => |
ed9b1598d293
manage components of ci builds;
Fabian Huch <huch@in.tum.de>
parents:
80259
diff
changeset
|
859 |
Component(dir.name, dir.hg.id("default")))) |
80246 | 860 |
|
80260
ed9b1598d293
manage components of ci builds;
Fabian Huch <huch@in.tum.de>
parents:
80259
diff
changeset
|
861 |
private def poll: Future[Poller.Versions] = Future.fork { |
80246 | 862 |
Par_List.map((repo: Mercurial.Repository) => repo.pull(), |
863 |
isabelle_repository :: sync_dirs.map(_.hg)) |
|
864 |
||
80260
ed9b1598d293
manage components of ci builds;
Fabian Huch <huch@in.tum.de>
parents:
80259
diff
changeset
|
865 |
current |
ed9b1598d293
manage components of ci builds;
Fabian Huch <huch@in.tum.de>
parents:
80259
diff
changeset
|
866 |
} |
ed9b1598d293
manage components of ci builds;
Fabian Huch <huch@in.tum.de>
parents:
80259
diff
changeset
|
867 |
|
ed9b1598d293
manage components of ci builds;
Fabian Huch <huch@in.tum.de>
parents:
80259
diff
changeset
|
868 |
val init: Poller.State = Poller.State(current, poll) |
ed9b1598d293
manage components of ci builds;
Fabian Huch <huch@in.tum.de>
parents:
80259
diff
changeset
|
869 |
|
ed9b1598d293
manage components of ci builds;
Fabian Huch <huch@in.tum.de>
parents:
80259
diff
changeset
|
870 |
private def add_tasks(current: Poller.Versions, next: Poller.Versions): Unit = { |
ed9b1598d293
manage components of ci builds;
Fabian Huch <huch@in.tum.de>
parents:
80259
diff
changeset
|
871 |
val isabelle_updated = current.isabelle != next.isabelle |
ed9b1598d293
manage components of ci builds;
Fabian Huch <huch@in.tum.de>
parents:
80259
diff
changeset
|
872 |
val updated_components = |
ed9b1598d293
manage components of ci builds;
Fabian Huch <huch@in.tum.de>
parents:
80259
diff
changeset
|
873 |
next.components.zip(current.components).filter(_ != _).map(_._1.name).toSet |
80246 | 874 |
|
80260
ed9b1598d293
manage components of ci builds;
Fabian Huch <huch@in.tum.de>
parents:
80259
diff
changeset
|
875 |
synchronized_database("add_tasks") { |
ed9b1598d293
manage components of ci builds;
Fabian Huch <huch@in.tum.de>
parents:
80259
diff
changeset
|
876 |
for { |
ed9b1598d293
manage components of ci builds;
Fabian Huch <huch@in.tum.de>
parents:
80259
diff
changeset
|
877 |
ci_job <- ci_jobs |
80261
e3f472221f8f
add triggers to ci jobs: on commit vs timed;
Fabian Huch <huch@in.tum.de>
parents:
80260
diff
changeset
|
878 |
if ci_job.trigger == isabelle.CI_Build.On_Commit |
80260
ed9b1598d293
manage components of ci builds;
Fabian Huch <huch@in.tum.de>
parents:
80259
diff
changeset
|
879 |
if isabelle_updated || ci_job.components.exists(updated_components.contains) |
ed9b1598d293
manage components of ci builds;
Fabian Huch <huch@in.tum.de>
parents:
80259
diff
changeset
|
880 |
if !_state.pending.values.exists(_.kind == ci_job.name) |
80261
e3f472221f8f
add triggers to ci jobs: on commit vs timed;
Fabian Huch <huch@in.tum.de>
parents:
80260
diff
changeset
|
881 |
} { |
80319
f83f402bc9a4
use build_cluster in ci builds;
Fabian Huch <huch@in.tum.de>
parents:
80315
diff
changeset
|
882 |
val task = Task(CI_Build(ci_job), ci_job.hosts.hosts_spec, priority = Priority.low, |
f83f402bc9a4
use build_cluster in ci builds;
Fabian Huch <huch@in.tum.de>
parents:
80315
diff
changeset
|
883 |
isabelle_rev = "default") |
80261
e3f472221f8f
add triggers to ci jobs: on commit vs timed;
Fabian Huch <huch@in.tum.de>
parents:
80260
diff
changeset
|
884 |
_state = _state.add_pending(task) |
e3f472221f8f
add triggers to ci jobs: on commit vs timed;
Fabian Huch <huch@in.tum.de>
parents:
80260
diff
changeset
|
885 |
} |
80246 | 886 |
} |
887 |
} |
|
888 |
||
889 |
def loop_body(state: Poller.State): Poller.State = |
|
890 |
if (!state.next.is_finished) state |
|
891 |
else { |
|
892 |
state.next.join_result match { |
|
893 |
case Exn.Exn(exn) => |
|
894 |
echo_error_message("Could not reach repository: " + exn.getMessage) |
|
80260
ed9b1598d293
manage components of ci builds;
Fabian Huch <huch@in.tum.de>
parents:
80259
diff
changeset
|
895 |
Poller.State(state.current, poll) |
ed9b1598d293
manage components of ci builds;
Fabian Huch <huch@in.tum.de>
parents:
80259
diff
changeset
|
896 |
case Exn.Res(next) => |
ed9b1598d293
manage components of ci builds;
Fabian Huch <huch@in.tum.de>
parents:
80259
diff
changeset
|
897 |
if (state.current != next) { |
ed9b1598d293
manage components of ci builds;
Fabian Huch <huch@in.tum.de>
parents:
80259
diff
changeset
|
898 |
echo("Found new revisions: " + next) |
ed9b1598d293
manage components of ci builds;
Fabian Huch <huch@in.tum.de>
parents:
80259
diff
changeset
|
899 |
add_tasks(state.current, next) |
80246 | 900 |
} |
80260
ed9b1598d293
manage components of ci builds;
Fabian Huch <huch@in.tum.de>
parents:
80259
diff
changeset
|
901 |
Poller.State(next, poll) |
80246 | 902 |
} |
903 |
} |
|
904 |
} |
|
905 |
||
80261
e3f472221f8f
add triggers to ci jobs: on commit vs timed;
Fabian Huch <huch@in.tum.de>
parents:
80260
diff
changeset
|
906 |
class Timer( |
e3f472221f8f
add triggers to ci jobs: on commit vs timed;
Fabian Huch <huch@in.tum.de>
parents:
80260
diff
changeset
|
907 |
ci_jobs: List[isabelle.CI_Build.Job], |
e3f472221f8f
add triggers to ci jobs: on commit vs timed;
Fabian Huch <huch@in.tum.de>
parents:
80260
diff
changeset
|
908 |
store: Store, |
e3f472221f8f
add triggers to ci jobs: on commit vs timed;
Fabian Huch <huch@in.tum.de>
parents:
80260
diff
changeset
|
909 |
isabelle_repository: Mercurial.Repository, |
e3f472221f8f
add triggers to ci jobs: on commit vs timed;
Fabian Huch <huch@in.tum.de>
parents:
80260
diff
changeset
|
910 |
sync_dirs: List[Sync.Dir], |
e3f472221f8f
add triggers to ci jobs: on commit vs timed;
Fabian Huch <huch@in.tum.de>
parents:
80260
diff
changeset
|
911 |
progress: Progress |
e3f472221f8f
add triggers to ci jobs: on commit vs timed;
Fabian Huch <huch@in.tum.de>
parents:
80260
diff
changeset
|
912 |
) extends Loop_Process[Date]("Timer", store, progress) { |
e3f472221f8f
add triggers to ci jobs: on commit vs timed;
Fabian Huch <huch@in.tum.de>
parents:
80260
diff
changeset
|
913 |
|
e3f472221f8f
add triggers to ci jobs: on commit vs timed;
Fabian Huch <huch@in.tum.de>
parents:
80260
diff
changeset
|
914 |
private def add_tasks(previous: Date, next: Date): Unit = |
e3f472221f8f
add triggers to ci jobs: on commit vs timed;
Fabian Huch <huch@in.tum.de>
parents:
80260
diff
changeset
|
915 |
for (ci_job <-ci_jobs) |
e3f472221f8f
add triggers to ci jobs: on commit vs timed;
Fabian Huch <huch@in.tum.de>
parents:
80260
diff
changeset
|
916 |
ci_job.trigger match { |
e3f472221f8f
add triggers to ci jobs: on commit vs timed;
Fabian Huch <huch@in.tum.de>
parents:
80260
diff
changeset
|
917 |
case isabelle.CI_Build.Timed(in_interval) if in_interval(previous, next) => |
80319
f83f402bc9a4
use build_cluster in ci builds;
Fabian Huch <huch@in.tum.de>
parents:
80315
diff
changeset
|
918 |
val task = Task(CI_Build(ci_job), ci_job.hosts.hosts_spec, isabelle_rev = "default") |
80261
e3f472221f8f
add triggers to ci jobs: on commit vs timed;
Fabian Huch <huch@in.tum.de>
parents:
80260
diff
changeset
|
919 |
_state = _state.add_pending(task) |
e3f472221f8f
add triggers to ci jobs: on commit vs timed;
Fabian Huch <huch@in.tum.de>
parents:
80260
diff
changeset
|
920 |
case _ => |
e3f472221f8f
add triggers to ci jobs: on commit vs timed;
Fabian Huch <huch@in.tum.de>
parents:
80260
diff
changeset
|
921 |
} |
e3f472221f8f
add triggers to ci jobs: on commit vs timed;
Fabian Huch <huch@in.tum.de>
parents:
80260
diff
changeset
|
922 |
|
e3f472221f8f
add triggers to ci jobs: on commit vs timed;
Fabian Huch <huch@in.tum.de>
parents:
80260
diff
changeset
|
923 |
def init: Date = Date.now() |
e3f472221f8f
add triggers to ci jobs: on commit vs timed;
Fabian Huch <huch@in.tum.de>
parents:
80260
diff
changeset
|
924 |
def loop_body(previous: Date): Date = { |
e3f472221f8f
add triggers to ci jobs: on commit vs timed;
Fabian Huch <huch@in.tum.de>
parents:
80260
diff
changeset
|
925 |
val now = Date.now() |
e3f472221f8f
add triggers to ci jobs: on commit vs timed;
Fabian Huch <huch@in.tum.de>
parents:
80260
diff
changeset
|
926 |
add_tasks(previous, now) |
e3f472221f8f
add triggers to ci jobs: on commit vs timed;
Fabian Huch <huch@in.tum.de>
parents:
80260
diff
changeset
|
927 |
now |
e3f472221f8f
add triggers to ci jobs: on commit vs timed;
Fabian Huch <huch@in.tum.de>
parents:
80260
diff
changeset
|
928 |
} |
e3f472221f8f
add triggers to ci jobs: on commit vs timed;
Fabian Huch <huch@in.tum.de>
parents:
80260
diff
changeset
|
929 |
} |
e3f472221f8f
add triggers to ci jobs: on commit vs timed;
Fabian Huch <huch@in.tum.de>
parents:
80260
diff
changeset
|
930 |
|
80246 | 931 |
|
932 |
/* web server */ |
|
933 |
||
934 |
object Web_Server { |
|
80338 | 935 |
val Id = new Properties.String(Markup.ID) |
936 |
||
80246 | 937 |
object Page { |
938 |
val HOME = Path.basic("home") |
|
939 |
val OVERVIEW = Path.basic("overview") |
|
940 |
val BUILD = Path.basic("build") |
|
941 |
} |
|
942 |
||
943 |
object API { |
|
944 |
val BUILD_CANCEL = Path.explode("api/build/cancel") |
|
945 |
} |
|
946 |
||
947 |
object Cache { |
|
948 |
def empty: Cache = new Cache() |
|
949 |
} |
|
950 |
||
951 |
class Cache private(keep: Time = Time.minutes(1)) { |
|
80339 | 952 |
private var logs: Map[(String, Long), (Time, String)] = Map.empty |
80246 | 953 |
|
954 |
def update(store: Store, state: State): Unit = synchronized { |
|
955 |
logs = |
|
956 |
for { |
|
80339 | 957 |
((kind, id), (time, log)) <- logs |
80246 | 958 |
if time + keep > Time.now() |
80339 | 959 |
} yield (kind, id) -> (time, File.read(store.log_file(kind, id))) |
80246 | 960 |
} |
961 |
||
80339 | 962 |
def lookup(store: Store, kind: String, id: Long): String = synchronized { |
963 |
val name = (kind, id) |
|
80280
7987b33fb6c5
clarified context: operations now in build process;
Fabian Huch <huch@in.tum.de>
parents:
80279
diff
changeset
|
964 |
logs.get(name) match { |
80246 | 965 |
case Some((_, log)) => |
80280
7987b33fb6c5
clarified context: operations now in build process;
Fabian Huch <huch@in.tum.de>
parents:
80279
diff
changeset
|
966 |
logs += name -> (Time.now(), log) |
80246 | 967 |
case None => |
80339 | 968 |
logs += name -> (Time.now(), File.read(store.log_file(kind, id))) |
80246 | 969 |
} |
80280
7987b33fb6c5
clarified context: operations now in build process;
Fabian Huch <huch@in.tum.de>
parents:
80279
diff
changeset
|
970 |
logs(name)._2 |
80246 | 971 |
} |
972 |
} |
|
973 |
} |
|
974 |
||
975 |
class Web_Server(port: Int, paths: Web_App.Paths, store: Store, progress: Progress) |
|
976 |
extends Loop_Process[Unit]("Web_Server", store, progress) { |
|
977 |
import Web_App.* |
|
978 |
import Web_Server.* |
|
979 |
||
980 |
val cache = Cache.empty |
|
981 |
||
982 |
enum Model { |
|
983 |
case Error extends Model |
|
984 |
case Cancelled extends Model |
|
985 |
case Home(state: State) extends Model |
|
986 |
case Overview(kind: String, state: State) extends Model |
|
80339 | 987 |
case Details(build: Build, state: State, public: Boolean = true) extends Model |
80246 | 988 |
} |
989 |
||
990 |
object View { |
|
991 |
import HTML.* |
|
992 |
import More_HTML.* |
|
993 |
||
994 |
def render_if(cond: Boolean, body: XML.Body): XML.Body = if (cond) body else Nil |
|
995 |
||
996 |
def frontend_link(url: Url, xml: XML.Body): XML.Elem = |
|
997 |
link(url.toString, xml) + ("target" -> "_parent") |
|
998 |
||
999 |
def link_kind(kind: String): XML.Elem = |
|
1000 |
frontend_link(paths.frontend_url(Page.OVERVIEW, Markup.Kind(kind)), text(kind)) |
|
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
1001 |
def link_build(name: String, id: Long): XML.Elem = |
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
1002 |
frontend_link(paths.frontend_url(Page.BUILD, Markup.Name(name)), text("#" + id)) |
80246 | 1003 |
|
80258 | 1004 |
private def render_page(name: String)(body: => XML.Body): XML.Body = { |
1005 |
def nav_link(path: Path, s: String): XML.Elem = |
|
1006 |
frontend_link(paths.frontend_url(Page.HOME), text("Home")) |
|
1007 |
||
1008 |
More_HTML.header(List(nav(List(nav_link(Page.HOME, "home"))))) :: |
|
1009 |
main(chapter(name) :: body ::: Nil) :: Nil |
|
1010 |
} |
|
1011 |
||
1012 |
def render_home(state: State): XML.Body = render_page("Dashboard") { |
|
80246 | 1013 |
def render_kind(kind: String): XML.Elem = { |
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
1014 |
val running = state.get_running(kind).sortBy(_.id).reverse |
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
1015 |
val finished = state.get_finished(kind).sortBy(_.id).reverse |
80246 | 1016 |
|
1017 |
def render_previous(finished: List[Result]): XML.Body = { |
|
1018 |
val (failed, rest) = finished.span(_.status != Status.ok) |
|
1019 |
val first_failed = failed.lastOption.map(result => |
|
1020 |
par( |
|
1021 |
text("first failure: ") ::: |
|
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
1022 |
link_build(result.name, result.id) :: |
80342
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
1023 |
text(" on " + result.start_date))) |
80246 | 1024 |
val last_success = rest.headOption.map(result => |
1025 |
par( |
|
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
1026 |
text("last success: ") ::: link_build(result.name, result.id) :: |
80342
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
1027 |
text(" on " + result.start_date))) |
80246 | 1028 |
first_failed.toList ::: last_success.toList |
1029 |
} |
|
1030 |
||
1031 |
def render_job(job: Job): XML.Body = |
|
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
1032 |
par(link_build(job.name, job.id) :: text(": running since " + job.start_date)) :: |
80283
c19f44f6525a
omit showing previous failures for user builds;
Fabian Huch <huch@in.tum.de>
parents:
80282
diff
changeset
|
1033 |
render_if( |
c19f44f6525a
omit showing previous failures for user builds;
Fabian Huch <huch@in.tum.de>
parents:
80282
diff
changeset
|
1034 |
finished.headOption.exists(_.status != Status.ok) && job.kind != User_Build.name, |
c19f44f6525a
omit showing previous failures for user builds;
Fabian Huch <huch@in.tum.de>
parents:
80282
diff
changeset
|
1035 |
render_previous(finished)) |
80246 | 1036 |
|
1037 |
def render_result(result: Result): XML.Body = |
|
1038 |
par( |
|
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
1039 |
link_build(result.name, result.id) :: |
80342
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
1040 |
text(" (" + result.status.toString + ") on " + result.start_date)) :: |
80258 | 1041 |
render_if(result.status != Status.ok && result.kind != User_Build.name, |
1042 |
render_previous(finished.tail)) |
|
80246 | 1043 |
|
1044 |
fieldset( |
|
1045 |
XML.elem("legend", List(link_kind(kind))) :: |
|
1046 |
(if (running.nonEmpty) render_job(running.head) |
|
1047 |
else if (finished.nonEmpty) render_result(finished.head) |
|
1048 |
else Nil)) |
|
1049 |
} |
|
1050 |
||
80258 | 1051 |
text("Queue: " + state.pending.size + " tasks waiting") ::: |
1052 |
section("Builds") :: par(text("Total: " + state.num_builds + " builds")) :: |
|
1053 |
state.kinds.map(render_kind) |
|
80246 | 1054 |
} |
1055 |
||
80258 | 1056 |
def render_overview(kind: String, state: State): XML.Body = |
1057 |
render_page("Overview: " + kind + " job ") { |
|
1058 |
def render_job(job: Job): XML.Body = |
|
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
1059 |
List(par(link_build(job.name, job.id) :: text(" running since " + job.start_date))) |
80246 | 1060 |
|
80258 | 1061 |
def render_result(result: Result): XML.Body = |
1062 |
List(par( |
|
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
1063 |
link_build(result.name, result.id) :: |
80342
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
1064 |
text(" (" + result.status + ") on " + result.start_date))) |
80246 | 1065 |
|
1066 |
itemize( |
|
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
1067 |
state.get_running(kind).sortBy(_.id).reverse.map(render_job) ::: |
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
1068 |
state.get_finished(kind).sortBy(_.id).reverse.map(render_result)) :: Nil |
80258 | 1069 |
} |
80246 | 1070 |
|
1071 |
private val ID = Params.key(Markup.ID) |
|
1072 |
||
80339 | 1073 |
def render_details(build: Build, state: State, public: Boolean): XML.Body = |
1074 |
render_page("Build: " + build.name) { |
|
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
1075 |
def render_cancel(uuid: UUID.T): XML.Body = |
80258 | 1076 |
render_if(!public, List( |
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
1077 |
submit_form("", List(hidden(ID, uuid.toString), |
80258 | 1078 |
api_button(paths.api_route(API.BUILD_CANCEL), "cancel build"))))) |
80246 | 1079 |
|
80258 | 1080 |
def render_rev(isabelle_rev: String, components: List[Component]): XML.Body = |
1081 |
for { |
|
1082 |
component <- Component("Isabelle", isabelle_rev) :: components |
|
1083 |
if component.rev.nonEmpty |
|
1084 |
} yield par(text(component.toString)) |
|
80246 | 1085 |
|
80339 | 1086 |
build match { |
80258 | 1087 |
case task: Task => |
1088 |
par(text("Task from " + task.submit_date + ". ")) :: |
|
1089 |
render_rev(task.isabelle_rev, task.components) ::: |
|
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
1090 |
render_cancel(task.uuid) |
80258 | 1091 |
case job: Job => |
1092 |
par(text("Start: " + job.start_date)) :: |
|
1093 |
par( |
|
1094 |
if (job.cancelled) text("Cancelling...") |
|
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
1095 |
else text("Running...") ::: render_cancel(job.uuid)) :: |
80258 | 1096 |
render_rev(job.isabelle_rev, job.components) ::: |
80339 | 1097 |
source(cache.lookup(store, job.kind, job.id)) :: Nil |
80258 | 1098 |
case result: Result => |
80342
35bee9c44e1a
use build log in build manager to store meta-data persistently;
Fabian Huch <huch@in.tum.de>
parents:
80340
diff
changeset
|
1099 |
par(text("Date: " + result.start_date)) :: |
80258 | 1100 |
par(text("Status: " + result.status)) :: |
80339 | 1101 |
source(cache.lookup(store, result.kind, result.id)) :: Nil |
80258 | 1102 |
} |
1103 |
} |
|
80246 | 1104 |
|
1105 |
def render_cancelled: XML.Body = |
|
1106 |
List(chapter("Build Cancelled"), frontend_link(paths.frontend_url(Page.HOME), text("Home"))) |
|
1107 |
||
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
1108 |
def parse_uuid(params: Params.Data): Option[UUID.T] = |
80246 | 1109 |
for { |
1110 |
id <- params.get(ID) |
|
1111 |
uuid <- UUID.unapply(id) |
|
1112 |
} yield uuid |
|
1113 |
} |
|
1114 |
||
1115 |
private val server = new Server[Model](paths, port, progress = progress) { |
|
1116 |
/* control */ |
|
1117 |
||
1118 |
def overview: Some[Model.Home] = Some(Model.Home(_state)) |
|
1119 |
||
1120 |
def get_overview(props: Properties.T): Option[Model.Overview] = |
|
1121 |
props match { |
|
1122 |
case Markup.Kind(kind) => Some(Model.Overview(kind, _state)) |
|
1123 |
case _ => None |
|
1124 |
} |
|
1125 |
||
80339 | 1126 |
def get_build(props: Properties.T): Option[Model.Details] = |
80246 | 1127 |
props match { |
1128 |
case Markup.Name(name) => |
|
1129 |
val state = _state |
|
80339 | 1130 |
state.get(name).map(Model.Details(_, state)) |
80338 | 1131 |
case Web_Server.Id(UUID(uuid)) => |
80246 | 1132 |
val state = _state |
80339 | 1133 |
state.get(uuid).map(Model.Details(_, state, public = false)) |
80246 | 1134 |
case _ => None |
1135 |
} |
|
1136 |
||
1137 |
def cancel_build(params: Params.Data): Option[Model] = |
|
1138 |
for { |
|
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
1139 |
uuid <- View.parse_uuid(params) |
80246 | 1140 |
model <- |
1141 |
synchronized_database("cancel_build") { |
|
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
1142 |
_state.get(uuid).map { |
80246 | 1143 |
case task: Task => |
1144 |
_state = _state.remove_pending(task.name) |
|
1145 |
Model.Cancelled |
|
1146 |
case job: Job => |
|
1147 |
val job1 = job.copy(cancelled = true) |
|
1148 |
_state = _state |
|
1149 |
.remove_running(job.name) |
|
1150 |
.add_running(job1) |
|
80339 | 1151 |
Model.Details(job1, _state, public = false) |
1152 |
case result: Result => Model.Details(result, _state, public = false) |
|
80246 | 1153 |
} |
1154 |
} |
|
1155 |
} yield model |
|
1156 |
||
1157 |
def render(model: Model): XML.Body = |
|
1158 |
HTML.title("Isabelle Build Manager") :: ( |
|
1159 |
model match { |
|
1160 |
case Model.Error => HTML.text("invalid request") |
|
1161 |
case Model.Home(state) => View.render_home(state) |
|
1162 |
case Model.Overview(kind, state) => View.render_overview(kind, state) |
|
80339 | 1163 |
case Model.Details(build, state, public) => View.render_details(build, state, public) |
80246 | 1164 |
case Model.Cancelled => View.render_cancelled |
1165 |
}) |
|
1166 |
||
1167 |
val error_model: Model = Model.Error |
|
1168 |
val endpoints = List( |
|
1169 |
Get(Page.HOME, "home", _ => overview), |
|
1170 |
Get(Page.OVERVIEW, "overview", get_overview), |
|
1171 |
Get(Page.BUILD, "build", get_build), |
|
80259
06a473ad2777
use external CSS for build manager page;
Fabian Huch <huch@in.tum.de>
parents:
80258
diff
changeset
|
1172 |
Post(API.BUILD_CANCEL, "cancel build", cancel_build)) |
80315 | 1173 |
val logo = Bytes.read(Path.explode("$ISABELLE_HOME/lib/logo/isabelle_transparent-48.gif")) |
80259
06a473ad2777
use external CSS for build manager page;
Fabian Huch <huch@in.tum.de>
parents:
80258
diff
changeset
|
1174 |
val head = |
06a473ad2777
use external CSS for build manager page;
Fabian Huch <huch@in.tum.de>
parents:
80258
diff
changeset
|
1175 |
List( |
80320 | 1176 |
HTML.title("Isabelle Build Manager"), |
80315 | 1177 |
Web_App.More_HTML.icon("data:image/x-icon;base64," + logo.encode_base64), |
80259
06a473ad2777
use external CSS for build manager page;
Fabian Huch <huch@in.tum.de>
parents:
80258
diff
changeset
|
1178 |
HTML.style_file("https://hawkz.github.io/gdcss/gd.css"), |
06a473ad2777
use external CSS for build manager page;
Fabian Huch <huch@in.tum.de>
parents:
80258
diff
changeset
|
1179 |
HTML.style("html { background-color: white; }")) |
80246 | 1180 |
} |
1181 |
||
1182 |
def init: Unit = server.start() |
|
1183 |
def loop_body(u: Unit): Unit = { |
|
1184 |
if (progress.stopped) server.stop() |
|
1185 |
else synchronized_database("iterate") { cache.update(store, _state) } |
|
1186 |
} |
|
1187 |
} |
|
1188 |
||
1189 |
||
1190 |
/* context */ |
|
1191 |
||
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
1192 |
case class Context(store: Store, task: Task, id: Long) { |
80339 | 1193 |
def name = Build.name(task.kind, id) |
1194 |
def progress: Progress = new File_Progress(store.log_file(task.kind, id)) |
|
80281
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
1195 |
|
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
1196 |
def task_dir: Path = store.task_dir(task) |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
1197 |
|
80339 | 1198 |
def init(): Unit = Isabelle_System.make_directory(store.log_file(task.kind, id).dir) |
80281
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
1199 |
|
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
1200 |
def isabelle_identifier: String = |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
1201 |
if (task.build_cluster) store.options.string("build_cluster_identifier") else store.identifier |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
1202 |
|
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
1203 |
def open_ssh(): SSH.System = { |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
1204 |
if (task.build_cluster) store.open_ssh() |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
1205 |
else Library.the_single(task.build_hosts).open_ssh(store.options) |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
1206 |
} |
80279
02424b81472a
clarified: add explicit build process;
Fabian Huch <huch@in.tum.de>
parents:
80278
diff
changeset
|
1207 |
} |
02424b81472a
clarified: add explicit build process;
Fabian Huch <huch@in.tum.de>
parents:
80278
diff
changeset
|
1208 |
|
02424b81472a
clarified: add explicit build process;
Fabian Huch <huch@in.tum.de>
parents:
80278
diff
changeset
|
1209 |
|
02424b81472a
clarified: add explicit build process;
Fabian Huch <huch@in.tum.de>
parents:
80278
diff
changeset
|
1210 |
/* build process */ |
02424b81472a
clarified: add explicit build process;
Fabian Huch <huch@in.tum.de>
parents:
80278
diff
changeset
|
1211 |
|
02424b81472a
clarified: add explicit build process;
Fabian Huch <huch@in.tum.de>
parents:
80278
diff
changeset
|
1212 |
object Build_Process { |
80280
7987b33fb6c5
clarified context: operations now in build process;
Fabian Huch <huch@in.tum.de>
parents:
80279
diff
changeset
|
1213 |
def open(context: Context): Build_Process = new Build_Process(context.open_ssh(), context) |
80279
02424b81472a
clarified: add explicit build process;
Fabian Huch <huch@in.tum.de>
parents:
80278
diff
changeset
|
1214 |
} |
80246 | 1215 |
|
80281
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
1216 |
class Build_Process(ssh: SSH.System, context: Context) { |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
1217 |
private val task = context.task |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
1218 |
private val progress = context.progress |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
1219 |
|
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
1220 |
|
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
1221 |
/* resources with cleanup operations */ |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
1222 |
|
80279
02424b81472a
clarified: add explicit build process;
Fabian Huch <huch@in.tum.de>
parents:
80278
diff
changeset
|
1223 |
private val _dir = ssh.tmp_dir() |
02424b81472a
clarified: add explicit build process;
Fabian Huch <huch@in.tum.de>
parents:
80278
diff
changeset
|
1224 |
private val _isabelle = |
02424b81472a
clarified: add explicit build process;
Fabian Huch <huch@in.tum.de>
parents:
80278
diff
changeset
|
1225 |
try { |
02424b81472a
clarified: add explicit build process;
Fabian Huch <huch@in.tum.de>
parents:
80278
diff
changeset
|
1226 |
val rsync_context = Rsync.Context(ssh = ssh) |
80280
7987b33fb6c5
clarified context: operations now in build process;
Fabian Huch <huch@in.tum.de>
parents:
80279
diff
changeset
|
1227 |
val source = File.standard_path(context.task_dir) |
80279
02424b81472a
clarified: add explicit build process;
Fabian Huch <huch@in.tum.de>
parents:
80278
diff
changeset
|
1228 |
Rsync.exec(rsync_context, clean = true, args = List("--", Url.direct_path(source), |
02424b81472a
clarified: add explicit build process;
Fabian Huch <huch@in.tum.de>
parents:
80278
diff
changeset
|
1229 |
rsync_context.target(_dir))).check |
02424b81472a
clarified: add explicit build process;
Fabian Huch <huch@in.tum.de>
parents:
80278
diff
changeset
|
1230 |
|
80280
7987b33fb6c5
clarified context: operations now in build process;
Fabian Huch <huch@in.tum.de>
parents:
80279
diff
changeset
|
1231 |
Isabelle_System.rm_tree(context.task_dir) |
80281
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
1232 |
Other_Isabelle(_dir, context.isabelle_identifier, ssh, progress) |
80279
02424b81472a
clarified: add explicit build process;
Fabian Huch <huch@in.tum.de>
parents:
80278
diff
changeset
|
1233 |
} |
02424b81472a
clarified: add explicit build process;
Fabian Huch <huch@in.tum.de>
parents:
80278
diff
changeset
|
1234 |
catch { case exn: Throwable => close(); throw exn } |
80246 | 1235 |
|
80279
02424b81472a
clarified: add explicit build process;
Fabian Huch <huch@in.tum.de>
parents:
80278
diff
changeset
|
1236 |
private val _process = |
02424b81472a
clarified: add explicit build process;
Fabian Huch <huch@in.tum.de>
parents:
80278
diff
changeset
|
1237 |
try { |
02424b81472a
clarified: add explicit build process;
Fabian Huch <huch@in.tum.de>
parents:
80278
diff
changeset
|
1238 |
val init_components = |
02424b81472a
clarified: add explicit build process;
Fabian Huch <huch@in.tum.de>
parents:
80278
diff
changeset
|
1239 |
for { |
80281
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
1240 |
component <- task.build_config.components |
80279
02424b81472a
clarified: add explicit build process;
Fabian Huch <huch@in.tum.de>
parents:
80278
diff
changeset
|
1241 |
target = _dir + Sync.DIRS + Path.basic(component.name) |
02424b81472a
clarified: add explicit build process;
Fabian Huch <huch@in.tum.de>
parents:
80278
diff
changeset
|
1242 |
if Components.is_component_dir(target) |
02424b81472a
clarified: add explicit build process;
Fabian Huch <huch@in.tum.de>
parents:
80278
diff
changeset
|
1243 |
} yield "init_component " + quote(target.absolute.implode) |
02424b81472a
clarified: add explicit build process;
Fabian Huch <huch@in.tum.de>
parents:
80278
diff
changeset
|
1244 |
|
02424b81472a
clarified: add explicit build process;
Fabian Huch <huch@in.tum.de>
parents:
80278
diff
changeset
|
1245 |
_isabelle.init( |
02424b81472a
clarified: add explicit build process;
Fabian Huch <huch@in.tum.de>
parents:
80278
diff
changeset
|
1246 |
other_settings = _isabelle.init_components() ::: init_components, |
80281
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
1247 |
fresh = task.build_config.fresh_build, echo = true) |
80246 | 1248 |
|
80281
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
1249 |
val cmd = task.build_config.command(task.build_hosts) |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
1250 |
progress.echo("isabelle" + cmd) |
80246 | 1251 |
|
80279
02424b81472a
clarified: add explicit build process;
Fabian Huch <huch@in.tum.de>
parents:
80278
diff
changeset
|
1252 |
val script = File.bash_path(Isabelle_Tool.exe(_isabelle.isabelle_home)) + cmd |
02424b81472a
clarified: add explicit build process;
Fabian Huch <huch@in.tum.de>
parents:
80278
diff
changeset
|
1253 |
ssh.bash_process(_isabelle.bash_context(script), settings = false) |
02424b81472a
clarified: add explicit build process;
Fabian Huch <huch@in.tum.de>
parents:
80278
diff
changeset
|
1254 |
} |
02424b81472a
clarified: add explicit build process;
Fabian Huch <huch@in.tum.de>
parents:
80278
diff
changeset
|
1255 |
catch { case exn: Throwable => close(); throw exn } |
80246 | 1256 |
|
80279
02424b81472a
clarified: add explicit build process;
Fabian Huch <huch@in.tum.de>
parents:
80278
diff
changeset
|
1257 |
def cancel(): Unit = Option(_process).foreach(_.interrupt()) |
02424b81472a
clarified: add explicit build process;
Fabian Huch <huch@in.tum.de>
parents:
80278
diff
changeset
|
1258 |
|
02424b81472a
clarified: add explicit build process;
Fabian Huch <huch@in.tum.de>
parents:
80278
diff
changeset
|
1259 |
def close(): Unit = { |
02424b81472a
clarified: add explicit build process;
Fabian Huch <huch@in.tum.de>
parents:
80278
diff
changeset
|
1260 |
Option(_dir).foreach(ssh.rm_tree) |
80280
7987b33fb6c5
clarified context: operations now in build process;
Fabian Huch <huch@in.tum.de>
parents:
80279
diff
changeset
|
1261 |
Isabelle_System.rm_tree(context.task_dir) |
80246 | 1262 |
ssh.close() |
1263 |
} |
|
80281
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
1264 |
|
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
1265 |
|
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
1266 |
/* execution */ |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
1267 |
|
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
1268 |
def run(): Process_Result = { |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
1269 |
val process_result = |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
1270 |
_process.result(progress_stdout = progress.echo(_), progress_stderr = progress.echo(_)) |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
1271 |
close() |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
1272 |
process_result |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
1273 |
} |
80246 | 1274 |
} |
1275 |
||
1276 |
||
1277 |
/* build manager store */ |
|
1278 |
||
1279 |
case class Store(options: Options) { |
|
1280 |
val base_dir = Path.explode(options.string("build_manager_dir")) |
|
1281 |
val identifier = options.string("build_manager_identifier") |
|
1282 |
||
80336 | 1283 |
val pending = base_dir + Path.basic("pending") |
1284 |
val finished = base_dir + Path.basic("finished") |
|
80252
96543177ab7e
build manager: manage directories/permissions, to minimize local administration;
Fabian Huch <huch@in.tum.de>
parents:
80251
diff
changeset
|
1285 |
|
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
1286 |
def task_dir(task: Task) = pending + Path.basic(task.uuid.toString) |
80340
992bd899a027
improve build manager log (for build_log);
Fabian Huch <huch@in.tum.de>
parents:
80339
diff
changeset
|
1287 |
def log_file(kind: String, id: Long): Path = |
992bd899a027
improve build manager log (for build_log);
Fabian Huch <huch@in.tum.de>
parents:
80339
diff
changeset
|
1288 |
finished + Path.make(List(kind, id.toString, "build-manager")).log |
80252
96543177ab7e
build manager: manage directories/permissions, to minimize local administration;
Fabian Huch <huch@in.tum.de>
parents:
80251
diff
changeset
|
1289 |
|
96543177ab7e
build manager: manage directories/permissions, to minimize local administration;
Fabian Huch <huch@in.tum.de>
parents:
80251
diff
changeset
|
1290 |
def sync_permissions(dir: Path, ssh: SSH.System = SSH.Local): Unit = { |
96543177ab7e
build manager: manage directories/permissions, to minimize local administration;
Fabian Huch <huch@in.tum.de>
parents:
80251
diff
changeset
|
1291 |
ssh.execute("chmod -R g+rwx " + File.bash_path(dir)) |
96543177ab7e
build manager: manage directories/permissions, to minimize local administration;
Fabian Huch <huch@in.tum.de>
parents:
80251
diff
changeset
|
1292 |
ssh.execute("chown -R :" + ssh_group + " " + File.bash_path(dir)) |
96543177ab7e
build manager: manage directories/permissions, to minimize local administration;
Fabian Huch <huch@in.tum.de>
parents:
80251
diff
changeset
|
1293 |
} |
96543177ab7e
build manager: manage directories/permissions, to minimize local administration;
Fabian Huch <huch@in.tum.de>
parents:
80251
diff
changeset
|
1294 |
|
96543177ab7e
build manager: manage directories/permissions, to minimize local administration;
Fabian Huch <huch@in.tum.de>
parents:
80251
diff
changeset
|
1295 |
def init_dirs(): Unit = |
80280
7987b33fb6c5
clarified context: operations now in build process;
Fabian Huch <huch@in.tum.de>
parents:
80279
diff
changeset
|
1296 |
List(pending, finished).foreach(dir => sync_permissions(Isabelle_System.make_directory(dir))) |
80252
96543177ab7e
build manager: manage directories/permissions, to minimize local administration;
Fabian Huch <huch@in.tum.de>
parents:
80251
diff
changeset
|
1297 |
|
80271 | 1298 |
val ssh_group: String = options.string("build_manager_ssh_group") |
80246 | 1299 |
|
1300 |
def open_ssh(): SSH.Session = |
|
1301 |
SSH.open_session(options, |
|
1302 |
host = options.string("build_manager_ssh_host"), |
|
1303 |
port = options.int("build_manager_ssh_port"), |
|
1304 |
user = options.string("build_manager_ssh_user")) |
|
1305 |
||
1306 |
def open_database(server: SSH.Server = SSH.no_server): PostgreSQL.Database = |
|
1307 |
PostgreSQL.open_database_server(options, server = server, |
|
1308 |
user = options.string("build_manager_database_user"), |
|
1309 |
password = options.string("build_manager_database_password"), |
|
1310 |
database = options.string("build_manager_database_name"), |
|
1311 |
host = options.string("build_manager_database_host"), |
|
1312 |
port = options.int("build_manager_database_port"), |
|
1313 |
ssh_host = options.string("build_manager_database_ssh_host"), |
|
1314 |
ssh_port = options.int("build_manager_database_ssh_port"), |
|
1315 |
ssh_user = options.string("build_manager_database_ssh_user")) |
|
1316 |
||
1317 |
def open_postgresql_server(): SSH.Server = |
|
1318 |
PostgreSQL.open_server(options, |
|
1319 |
host = options.string("build_manager_database_host"), |
|
1320 |
port = options.int("build_manager_database_port"), |
|
1321 |
ssh_host = options.string("build_manager_ssh_host"), |
|
1322 |
ssh_port = options.int("build_manager_ssh_port"), |
|
1323 |
ssh_user = options.string("build_manager_ssh_user")) |
|
1324 |
} |
|
1325 |
||
1326 |
||
1327 |
/* build manager */ |
|
1328 |
||
1329 |
def build_manager( |
|
1330 |
build_hosts: List[Build_Cluster.Host], |
|
1331 |
options: Options, |
|
1332 |
port: Int, |
|
1333 |
sync_dirs: List[Sync.Dir] = Nil, |
|
1334 |
progress: Progress = new Progress |
|
1335 |
): Unit = { |
|
1336 |
val store = Store(options) |
|
1337 |
val isabelle_repository = Mercurial.self_repository() |
|
80260
ed9b1598d293
manage components of ci builds;
Fabian Huch <huch@in.tum.de>
parents:
80259
diff
changeset
|
1338 |
val ci_jobs = |
ed9b1598d293
manage components of ci builds;
Fabian Huch <huch@in.tum.de>
parents:
80259
diff
changeset
|
1339 |
space_explode(',', options.string("build_manager_ci_jobs")).map(isabelle.CI_Build.the_job) |
80246 | 1340 |
val url = Url(options.string("build_manager_address")) |
1341 |
val paths = Web_App.Paths(url, Path.current, true, Web_Server.Page.HOME) |
|
1342 |
||
1343 |
using(store.open_database())(db => |
|
1344 |
Build_Manager.private_data.transaction_lock(db, |
|
80252
96543177ab7e
build manager: manage directories/permissions, to minimize local administration;
Fabian Huch <huch@in.tum.de>
parents:
80251
diff
changeset
|
1345 |
create = true, label = "Build_Manager.build_manager") { store.init_dirs() }) |
80246 | 1346 |
|
1347 |
val processes = List( |
|
1348 |
new Runner(store, build_hosts, isabelle_repository, sync_dirs, progress), |
|
1349 |
new Poller(ci_jobs, store, isabelle_repository, sync_dirs, progress), |
|
80261
e3f472221f8f
add triggers to ci jobs: on commit vs timed;
Fabian Huch <huch@in.tum.de>
parents:
80260
diff
changeset
|
1350 |
new Timer(ci_jobs, store, isabelle_repository, sync_dirs, progress), |
80246 | 1351 |
new Web_Server(port, paths, store, progress)) |
1352 |
||
1353 |
val threads = processes.map(Isabelle_Thread.create(_)) |
|
1354 |
POSIX_Interrupt.handler { |
|
1355 |
progress.stop() |
|
1356 |
processes.foreach(_.interrupt()) |
|
1357 |
} { |
|
1358 |
threads.foreach(_.start()) |
|
1359 |
threads.foreach(_.join()) |
|
1360 |
} |
|
1361 |
} |
|
1362 |
||
80334 | 1363 |
|
1364 |
/* Isabelle tool wrapper */ |
|
1365 |
||
1366 |
private def show_options(relevant_options: List[String], options: Options): String = |
|
1367 |
cat_lines(relevant_options.flatMap(options.get).map(_.print)) |
|
1368 |
||
1369 |
private val notable_server_options = |
|
1370 |
List( |
|
1371 |
"build_manager_dir", |
|
1372 |
"build_manager_address", |
|
1373 |
"build_manager_ssh_host", |
|
1374 |
"build_manager_ssh_group", |
|
1375 |
"build_manager_ci_jobs") |
|
1376 |
||
1377 |
val isabelle_tool = Isabelle_Tool("build_manager", "run build manager", Scala_Project.here, |
|
1378 |
{ args => |
|
1379 |
var afp_root: Option[Path] = None |
|
1380 |
val dirs = new mutable.ListBuffer[Path] |
|
1381 |
val build_hosts = new mutable.ListBuffer[Build_Cluster.Host] |
|
1382 |
var options = Options.init() |
|
1383 |
var port = 8080 |
|
1384 |
||
1385 |
val getopts = Getopts(""" |
|
1386 |
Usage: isabelle build_manager [OPTIONS] |
|
1387 |
||
1388 |
Options are: |
|
1389 |
-A ROOT include AFP with given root directory (":" for """ + AFP.BASE.implode + """) |
|
1390 |
-D DIR include extra component in given directory |
|
1391 |
-H HOSTS host specifications for all available hosts of the form |
|
1392 |
NAMES:PARAMETERS (separated by commas) |
|
1393 |
-o OPTION override Isabelle system OPTION (via NAME=VAL or NAME) |
|
1394 |
-p PORT explicit web server port |
|
1395 |
||
1396 |
Run Isabelle build manager. Notable system options: |
|
1397 |
||
1398 |
""" + Library.indent_lines(2, show_options(notable_server_options, options)) + "\n", |
|
1399 |
"A:" -> (arg => afp_root = Some(if (arg == ":") AFP.BASE else Path.explode(arg))), |
|
1400 |
"D:" -> (arg => dirs += Path.explode(arg)), |
|
1401 |
"H:" -> (arg => build_hosts ++= Build_Cluster.Host.parse(Registry.global, arg)), |
|
1402 |
"o:" -> (arg => options = options + arg), |
|
1403 |
"p:" -> (arg => port = Value.Int.parse(arg))) |
|
1404 |
||
1405 |
val more_args = getopts(args) |
|
1406 |
if (more_args.nonEmpty) getopts.usage() |
|
1407 |
||
1408 |
val progress = new Console_Progress() |
|
1409 |
val sync_dirs = |
|
1410 |
Sync.afp_dirs(afp_root) ::: dirs.toList.map(dir => Sync.Dir(dir.file_name, dir)) |
|
1411 |
||
1412 |
sync_dirs.foreach(_.check()) |
|
1413 |
||
1414 |
build_manager(build_hosts = build_hosts.toList, options = options, port = port, |
|
1415 |
sync_dirs = sync_dirs, progress = progress) |
|
1416 |
}) |
|
1417 |
||
1418 |
||
80343
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1419 |
/* restore build manager database */ |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1420 |
|
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1421 |
def build_manager_database(options: Options, progress: Progress = new Progress): Unit = { |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1422 |
val store = Store(options) |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1423 |
using(store.open_database()) { db => |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1424 |
db.transaction { |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1425 |
val tables0 = Build_Manager.private_data.tables.list |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1426 |
val tables = tables0.filter(t => db.exists_table(t.name)) |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1427 |
if (tables.nonEmpty) { |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1428 |
progress.echo("Removing tables " + commas_quote(tables.map(_.name)) + " ...") |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1429 |
db.execute_statement(SQL.MULTI(tables.map(db.destroy))) |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1430 |
} |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1431 |
} |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1432 |
|
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1433 |
val results = |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1434 |
for { |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1435 |
kind <- File.read_dir(store.finished) |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1436 |
entry <- File.read_dir(store.finished + Path.basic(kind)) |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1437 |
id <- Value.Long.unapply(entry) |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1438 |
log_file = store.log_file(kind, id) |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1439 |
if log_file.is_file |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1440 |
} yield Result.read_log(store, kind, id) |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1441 |
|
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1442 |
val state = State(finished = results.map(result => result.name -> result).toMap) |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1443 |
|
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1444 |
Build_Manager.private_data.transaction_lock(db, |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1445 |
create = true, label = "Build_Manager.build_manager_database") { |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1446 |
|
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1447 |
progress.echo("Writing " + results.length + " results ...") |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1448 |
Build_Manager.private_data.push_state(db, State(), state) |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1449 |
} |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1450 |
} |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1451 |
} |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1452 |
|
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1453 |
|
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1454 |
/* Isabelle tool wrapper */ |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1455 |
|
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1456 |
val isabelle_tool1 = Isabelle_Tool("build_manager_database", |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1457 |
"restore build_manager database from log files", |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1458 |
Scala_Project.here, |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1459 |
{ args => |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1460 |
var options = Options.init() |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1461 |
|
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1462 |
val getopts = Getopts(""" |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1463 |
Usage: isabelle build_manager_database [OPTIONS] |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1464 |
|
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1465 |
Options are: |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1466 |
-o OPTION override Isabelle system OPTION (via NAME=VAL or NAME) |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1467 |
|
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1468 |
Restore build_manager database from log files. |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1469 |
""", |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1470 |
"o:" -> (arg => options = options + arg)) |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1471 |
|
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1472 |
val more_args = getopts(args) |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1473 |
if (more_args.nonEmpty) getopts.usage() |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1474 |
|
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1475 |
val progress = new Console_Progress() |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1476 |
|
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1477 |
build_manager_database(options, progress = progress) |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1478 |
}) |
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1479 |
|
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1480 |
|
80334 | 1481 |
/* build task */ |
1482 |
||
80246 | 1483 |
def build_task( |
1484 |
options: Options, |
|
1485 |
store: Store, |
|
1486 |
afp_root: Option[Path] = None, |
|
1487 |
base_sessions: List[String] = Nil, |
|
1488 |
presentation: Boolean = false, |
|
1489 |
requirements: Boolean = false, |
|
1490 |
exclude_session_groups: List[String] = Nil, |
|
1491 |
all_sessions: Boolean = false, |
|
1492 |
build_heap: Boolean = false, |
|
1493 |
clean_build: Boolean = false, |
|
1494 |
export_files: Boolean = false, |
|
1495 |
fresh_build: Boolean = false, |
|
1496 |
session_groups: List[String] = Nil, |
|
1497 |
sessions: List[String] = Nil, |
|
1498 |
prefs: List[Options.Spec] = Nil, |
|
1499 |
exclude_sessions: List[String] = Nil, |
|
80254
6b3374d208b8
add verbose option to build_task;
Fabian Huch <huch@in.tum.de>
parents:
80252
diff
changeset
|
1500 |
verbose: Boolean = false, |
80250
8ae6f4e8cc2a
allow explicit Isabelle rev in build task (e.g., for older Isabelle versions);
Fabian Huch <huch@in.tum.de>
parents:
80246
diff
changeset
|
1501 |
rev: String = "", |
80246 | 1502 |
progress: Progress = new Progress |
1503 |
): UUID.T = { |
|
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
1504 |
val uuid = UUID.random() |
80246 | 1505 |
val afp_rev = if (afp_root.nonEmpty) Some("") else None |
1506 |
||
80281
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
1507 |
val hosts_spec = options.string("build_manager_cluster") |
80338 | 1508 |
val paths = Web_App.Paths(Url(options.string("build_manager_address")), Path.current) |
1509 |
||
80281
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
1510 |
val build_config = User_Build(afp_rev, prefs, requirements, all_sessions, |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
1511 |
base_sessions, exclude_session_groups, exclude_sessions, session_groups, sessions, build_heap, |
17d2f775907a
add cluster/hosts configurations to build manager: allows running jobs in parallel on distinct hardware;
Fabian Huch <huch@in.tum.de>
parents:
80280
diff
changeset
|
1512 |
clean_build, export_files, fresh_build, presentation, verbose) |
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
1513 |
val task = Task(build_config, hosts_spec, uuid, Date.now(), Priority.high) |
80246 | 1514 |
|
80280
7987b33fb6c5
clarified context: operations now in build process;
Fabian Huch <huch@in.tum.de>
parents:
80279
diff
changeset
|
1515 |
val dir = store.task_dir(task) |
80246 | 1516 |
|
1517 |
progress.interrupt_handler { |
|
1518 |
using(store.open_ssh()) { ssh => |
|
80252
96543177ab7e
build manager: manage directories/permissions, to minimize local administration;
Fabian Huch <huch@in.tum.de>
parents:
80251
diff
changeset
|
1519 |
val rsync_context = Rsync.Context(ssh = ssh) |
80246 | 1520 |
progress.echo("Transferring repositories...") |
80280
7987b33fb6c5
clarified context: operations now in build process;
Fabian Huch <huch@in.tum.de>
parents:
80279
diff
changeset
|
1521 |
Sync.sync(store.options, rsync_context, dir, preserve_jars = true, |
80250
8ae6f4e8cc2a
allow explicit Isabelle rev in build task (e.g., for older Isabelle versions);
Fabian Huch <huch@in.tum.de>
parents:
80246
diff
changeset
|
1522 |
dirs = Sync.afp_dirs(afp_root), rev = rev) |
80280
7987b33fb6c5
clarified context: operations now in build process;
Fabian Huch <huch@in.tum.de>
parents:
80279
diff
changeset
|
1523 |
store.sync_permissions(dir, ssh) |
80246 | 1524 |
|
1525 |
if (progress.stopped) { |
|
1526 |
progress.echo("Cancelling submission...") |
|
80280
7987b33fb6c5
clarified context: operations now in build process;
Fabian Huch <huch@in.tum.de>
parents:
80279
diff
changeset
|
1527 |
ssh.rm_tree(dir) |
80246 | 1528 |
} else { |
1529 |
using(store.open_postgresql_server()) { server => |
|
1530 |
using(store.open_database(server = server)) { db => |
|
1531 |
Build_Manager.private_data.transaction_lock(db, label = "Build_Manager.build_task") { |
|
1532 |
val old_state = Build_Manager.private_data.pull_state(db, State()) |
|
1533 |
val state = old_state.add_pending(task) |
|
1534 |
Build_Manager.private_data.push_state(db, old_state, state) |
|
1535 |
} |
|
1536 |
} |
|
1537 |
} |
|
80338 | 1538 |
|
1539 |
val address = paths.frontend_url(Web_Server.Page.BUILD, Web_Server.Id(task.uuid.toString)) |
|
80246 | 1540 |
progress.echo("Submitted task. Private url: " + address) |
1541 |
} |
|
1542 |
} |
|
1543 |
} |
|
1544 |
||
80337
02f8a35ed8e2
clarified names: more canonical;
Fabian Huch <huch@in.tum.de>
parents:
80336
diff
changeset
|
1545 |
uuid |
80246 | 1546 |
} |
1547 |
||
1548 |
||
1549 |
/* Isabelle tool wrapper */ |
|
1550 |
||
80252
96543177ab7e
build manager: manage directories/permissions, to minimize local administration;
Fabian Huch <huch@in.tum.de>
parents:
80251
diff
changeset
|
1551 |
val notable_client_options = List("build_manager_ssh_user", "build_manager_ssh_group") |
96543177ab7e
build manager: manage directories/permissions, to minimize local administration;
Fabian Huch <huch@in.tum.de>
parents:
80251
diff
changeset
|
1552 |
|
80343
595b362ab851
add build_manager_database tool to restore db from log files;
Fabian Huch <huch@in.tum.de>
parents:
80342
diff
changeset
|
1553 |
val isabelle_tool2 = Isabelle_Tool("build_task", "submit build task for build manager", |
80246 | 1554 |
Scala_Project.here, |
1555 |
{ args => |
|
1556 |
var afp_root: Option[Path] = None |
|
1557 |
val base_sessions = new mutable.ListBuffer[String] |
|
1558 |
var presentation = false |
|
1559 |
var requirements = false |
|
1560 |
val exclude_session_groups = new mutable.ListBuffer[String] |
|
1561 |
var all_sessions = false |
|
1562 |
var build_heap = false |
|
1563 |
var clean_build = false |
|
1564 |
var export_files = false |
|
1565 |
var fresh_build = false |
|
1566 |
val session_groups = new mutable.ListBuffer[String] |
|
1567 |
var options = Options.init(specs = Options.Spec.ISABELLE_BUILD_OPTIONS) |
|
1568 |
var prefs: List[Options.Spec] = Nil |
|
80254
6b3374d208b8
add verbose option to build_task;
Fabian Huch <huch@in.tum.de>
parents:
80252
diff
changeset
|
1569 |
var verbose = false |
80250
8ae6f4e8cc2a
allow explicit Isabelle rev in build task (e.g., for older Isabelle versions);
Fabian Huch <huch@in.tum.de>
parents:
80246
diff
changeset
|
1570 |
var rev = "" |
80246 | 1571 |
val exclude_sessions = new mutable.ListBuffer[String] |
1572 |
||
1573 |
val getopts = Getopts(""" |
|
1574 |
Usage: isabelle build_task [OPTIONS] [SESSIONS ...] |
|
1575 |
||
1576 |
Options are: |
|
1577 |
-A ROOT include AFP with given root directory (":" for """ + AFP.BASE.implode + """) |
|
1578 |
-B NAME include session NAME and all descendants |
|
1579 |
-P enable HTML/PDF presentation |
|
1580 |
-R refer to requirements of selected sessions |
|
1581 |
-X NAME exclude sessions from group NAME and all descendants |
|
1582 |
-a select all sessions |
|
1583 |
-b build heap images |
|
1584 |
-c clean build |
|
1585 |
-e export files from session specification into file-system |
|
1586 |
-f fresh build |
|
1587 |
-g NAME select session group NAME |
|
1588 |
-o OPTION override Isabelle system OPTION (via NAME=VAL or NAME) |
|
1589 |
-p OPTIONS comma-separated preferences for build process |
|
80250
8ae6f4e8cc2a
allow explicit Isabelle rev in build task (e.g., for older Isabelle versions);
Fabian Huch <huch@in.tum.de>
parents:
80246
diff
changeset
|
1590 |
-r REV explicit revision (default: state of working directory) |
80254
6b3374d208b8
add verbose option to build_task;
Fabian Huch <huch@in.tum.de>
parents:
80252
diff
changeset
|
1591 |
-v verbose |
80246 | 1592 |
-x NAME exclude session NAME and all descendants |
1593 |
||
1594 |
Submit build task on SSH server. Notable system options: |
|
1595 |
||
80252
96543177ab7e
build manager: manage directories/permissions, to minimize local administration;
Fabian Huch <huch@in.tum.de>
parents:
80251
diff
changeset
|
1596 |
""" + Library.indent_lines(2, show_options(notable_client_options, options)) + "\n", |
80246 | 1597 |
"A:" -> (arg => afp_root = Some(if (arg == ":") AFP.BASE else Path.explode(arg))), |
1598 |
"B:" -> (arg => base_sessions += arg), |
|
1599 |
"P" -> (_ => presentation = true), |
|
1600 |
"R" -> (_ => requirements = true), |
|
1601 |
"X:" -> (arg => exclude_session_groups += arg), |
|
1602 |
"a" -> (_ => all_sessions = true), |
|
1603 |
"b" -> (_ => build_heap = true), |
|
1604 |
"c" -> (_ => clean_build = true), |
|
1605 |
"e" -> (_ => export_files = true), |
|
1606 |
"f" -> (_ => fresh_build = true), |
|
1607 |
"g:" -> (arg => session_groups += arg), |
|
1608 |
"o:" -> (arg => options = options + arg), |
|
1609 |
"p:" -> (arg => prefs = Options.Spec.parse(arg)), |
|
80250
8ae6f4e8cc2a
allow explicit Isabelle rev in build task (e.g., for older Isabelle versions);
Fabian Huch <huch@in.tum.de>
parents:
80246
diff
changeset
|
1610 |
"r:" -> (arg => rev = arg), |
80254
6b3374d208b8
add verbose option to build_task;
Fabian Huch <huch@in.tum.de>
parents:
80252
diff
changeset
|
1611 |
"v" -> (_ => verbose = true), |
80246 | 1612 |
"x:" -> (arg => exclude_sessions += arg)) |
1613 |
||
1614 |
val sessions = getopts(args) |
|
1615 |
val store = Store(options) |
|
1616 |
val progress = new Console_Progress() |
|
1617 |
||
1618 |
build_task(options, store = store, afp_root = afp_root, base_sessions = |
|
1619 |
base_sessions.toList, presentation = presentation, requirements = requirements, |
|
1620 |
exclude_session_groups = exclude_session_groups.toList, all_sessions = all_sessions, |
|
1621 |
build_heap = build_heap, clean_build = clean_build, export_files = export_files, |
|
1622 |
fresh_build = fresh_build, session_groups = session_groups.toList, sessions = sessions, |
|
80254
6b3374d208b8
add verbose option to build_task;
Fabian Huch <huch@in.tum.de>
parents:
80252
diff
changeset
|
1623 |
prefs = prefs, verbose = verbose, rev = rev, exclude_sessions = exclude_sessions.toList, |
6b3374d208b8
add verbose option to build_task;
Fabian Huch <huch@in.tum.de>
parents:
80252
diff
changeset
|
1624 |
progress = progress) |
80246 | 1625 |
}) |
1626 |
} |