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