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