| author | wenzelm |
| Sat, 20 Jan 2024 16:09:35 +0100 | |
| changeset 79503 | c67b47cd41dc |
| parent 78876 | 4222955f3b69 |
| child 79717 | da4e82434985 |
| permissions | -rw-r--r-- |
| 61276 | 1 |
/* Title: Pure/System/progress.scala |
2 |
Author: Makarius |
|
3 |
||
4 |
Progress context for system processes. |
|
5 |
*/ |
|
6 |
||
7 |
package isabelle |
|
8 |
||
9 |
||
| 73897 | 10 |
import java.util.{Map => JMap}
|
| 64201 | 11 |
import java.io.{File => JFile}
|
12 |
||
| 78155 | 13 |
import scala.collection.immutable.SortedMap |
14 |
||
| 64201 | 15 |
|
| 75393 | 16 |
object Progress {
|
| 78503 | 17 |
/* output */ |
18 |
||
19 |
sealed abstract class Output { def message: Message }
|
|
| 78155 | 20 |
|
| 78611 | 21 |
enum Kind { case writeln, warning, error_message }
|
| 78503 | 22 |
sealed case class Message( |
| 78611 | 23 |
kind: Kind, |
| 78503 | 24 |
text: String, |
25 |
verbose: Boolean = false |
|
26 |
) extends Output {
|
|
27 |
override def message: Message = this |
|
28 |
||
|
77502
2e2b2bd6b2d2
clarified signature: require just one "override def echo(message: Progress.Message): Unit";
wenzelm
parents:
77499
diff
changeset
|
29 |
def output_text: String = |
|
2e2b2bd6b2d2
clarified signature: require just one "override def echo(message: Progress.Message): Unit";
wenzelm
parents:
77499
diff
changeset
|
30 |
kind match {
|
|
2e2b2bd6b2d2
clarified signature: require just one "override def echo(message: Progress.Message): Unit";
wenzelm
parents:
77499
diff
changeset
|
31 |
case Kind.writeln => Output.writeln_text(text) |
|
2e2b2bd6b2d2
clarified signature: require just one "override def echo(message: Progress.Message): Unit";
wenzelm
parents:
77499
diff
changeset
|
32 |
case Kind.warning => Output.warning_text(text) |
|
2e2b2bd6b2d2
clarified signature: require just one "override def echo(message: Progress.Message): Unit";
wenzelm
parents:
77499
diff
changeset
|
33 |
case Kind.error_message => Output.error_message_text(text) |
|
2e2b2bd6b2d2
clarified signature: require just one "override def echo(message: Progress.Message): Unit";
wenzelm
parents:
77499
diff
changeset
|
34 |
} |
|
2e2b2bd6b2d2
clarified signature: require just one "override def echo(message: Progress.Message): Unit";
wenzelm
parents:
77499
diff
changeset
|
35 |
|
|
2e2b2bd6b2d2
clarified signature: require just one "override def echo(message: Progress.Message): Unit";
wenzelm
parents:
77499
diff
changeset
|
36 |
override def toString: String = output_text |
|
2e2b2bd6b2d2
clarified signature: require just one "override def echo(message: Progress.Message): Unit";
wenzelm
parents:
77499
diff
changeset
|
37 |
} |
|
2e2b2bd6b2d2
clarified signature: require just one "override def echo(message: Progress.Message): Unit";
wenzelm
parents:
77499
diff
changeset
|
38 |
|
| 78503 | 39 |
sealed case class Theory( |
40 |
theory: String, |
|
41 |
session: String = "", |
|
42 |
percentage: Option[Int] = None |
|
43 |
) extends Output {
|
|
|
77502
2e2b2bd6b2d2
clarified signature: require just one "override def echo(message: Progress.Message): Unit";
wenzelm
parents:
77499
diff
changeset
|
44 |
def message: Message = |
|
77509
3bc49507bae5
clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents:
77507
diff
changeset
|
45 |
Message(Kind.writeln, print_session + print_theory + print_percentage, verbose = true) |
| 68987 | 46 |
|
| 77504 | 47 |
def print_session: String = if_proper(session, session + ": ") |
| 68987 | 48 |
def print_theory: String = "theory " + theory |
49 |
def print_percentage: String = |
|
50 |
percentage match { case None => "" case Some(p) => " " + p + "%" }
|
|
| 68957 | 51 |
} |
| 78155 | 52 |
|
53 |
||
54 |
/* SQL data model */ |
|
55 |
||
|
78396
7853d9072d1b
renamed object Data to private_data, to emphasize its intended scope (but it is publicly accessible in the database);
wenzelm
parents:
78389
diff
changeset
|
56 |
object private_data extends SQL.Data("isabelle_progress") {
|
|
78170
c85eeff78b33
proper support for SQLite: avoid conflicts on transaction_lock;
wenzelm
parents:
78156
diff
changeset
|
57 |
val database: Path = Path.explode("$ISABELLE_HOME_USER/progress.db")
|
|
c85eeff78b33
proper support for SQLite: avoid conflicts on transaction_lock;
wenzelm
parents:
78156
diff
changeset
|
58 |
|
|
78187
2df0f3604a67
clarified signature: more explicit class SQL.Data;
wenzelm
parents:
78170
diff
changeset
|
59 |
override lazy val tables = SQL.Tables(Base.table, Agents.table, Messages.table) |
| 78155 | 60 |
|
61 |
object Base {
|
|
62 |
val context_uuid = SQL.Column.string("context_uuid").make_primary_key
|
|
63 |
val context = SQL.Column.long("context").make_primary_key
|
|
64 |
val stopped = SQL.Column.bool("stopped")
|
|
65 |
||
| 78266 | 66 |
val table = make_table(List(context_uuid, context, stopped)) |
| 78155 | 67 |
} |
68 |
||
69 |
object Agents {
|
|
70 |
val agent_uuid = SQL.Column.string("agent_uuid").make_primary_key
|
|
71 |
val context_uuid = SQL.Column.string("context_uuid").make_primary_key
|
|
| 78240 | 72 |
val kind = SQL.Column.string("kind")
|
| 78155 | 73 |
val hostname = SQL.Column.string("hostname")
|
74 |
val java_pid = SQL.Column.long("java_pid")
|
|
75 |
val java_start = SQL.Column.date("java_start")
|
|
76 |
val start = SQL.Column.date("start")
|
|
77 |
val stamp = SQL.Column.date("stamp")
|
|
78 |
val stop = SQL.Column.date("stop")
|
|
79 |
val seen = SQL.Column.long("seen")
|
|
80 |
||
| 78266 | 81 |
val table = |
82 |
make_table( |
|
83 |
List(agent_uuid, context_uuid, kind, hostname, java_pid, java_start, start, stamp, stop, seen), |
|
84 |
name = "agents") |
|
| 78155 | 85 |
} |
86 |
||
87 |
object Messages {
|
|
88 |
type T = SortedMap[Long, Message] |
|
89 |
val empty: T = SortedMap.empty |
|
90 |
||
91 |
val context = SQL.Column.long("context").make_primary_key
|
|
92 |
val serial = SQL.Column.long("serial").make_primary_key
|
|
93 |
val kind = SQL.Column.int("kind")
|
|
94 |
val text = SQL.Column.string("text")
|
|
95 |
val verbose = SQL.Column.bool("verbose")
|
|
96 |
||
| 78266 | 97 |
val table = make_table(List(context, serial, kind, text, verbose), name = "messages") |
| 78155 | 98 |
} |
99 |
||
100 |
def read_progress_context(db: SQL.Database, context_uuid: String): Option[Long] = |
|
101 |
db.execute_query_statementO( |
|
102 |
Base.table.select(List(Base.context), |
|
103 |
sql = Base.context_uuid.where_equal(context_uuid)), _.long(Base.context)) |
|
104 |
||
105 |
def next_progress_context(db: SQL.Database): Long = |
|
106 |
db.execute_query_statementO( |
|
107 |
Base.table.select(List(Base.context.max)), _.long(Base.context)).getOrElse(0L) + 1L |
|
108 |
||
109 |
def read_progress_stopped(db: SQL.Database, context: Long): Boolean = |
|
110 |
db.execute_query_statementO( |
|
111 |
Base.table.select(List(Base.stopped), sql = Base.context.where_equal(context)), |
|
112 |
_.bool(Base.stopped) |
|
113 |
).getOrElse(false) |
|
114 |
||
115 |
def write_progress_stopped(db: SQL.Database, context: Long, stopped: Boolean): Unit = |
|
116 |
db.execute_statement( |
|
117 |
Base.table.update(List(Base.stopped), sql = Base.context.where_equal(context)), |
|
118 |
body = { stmt => stmt.bool(1) = stopped })
|
|
119 |
||
120 |
def update_agent( |
|
121 |
db: SQL.Database, |
|
122 |
agent_uuid: String, |
|
123 |
seen: Long, |
|
|
78246
76dd9b9cf624
more robust "stop": further "stamp" ticks may happen afterwards;
wenzelm
parents:
78242
diff
changeset
|
124 |
stop_now: Boolean = false |
| 78155 | 125 |
): Unit = {
|
|
78246
76dd9b9cf624
more robust "stop": further "stamp" ticks may happen afterwards;
wenzelm
parents:
78242
diff
changeset
|
126 |
val sql = Agents.agent_uuid.where_equal(agent_uuid) |
|
76dd9b9cf624
more robust "stop": further "stamp" ticks may happen afterwards;
wenzelm
parents:
78242
diff
changeset
|
127 |
|
|
76dd9b9cf624
more robust "stop": further "stamp" ticks may happen afterwards;
wenzelm
parents:
78242
diff
changeset
|
128 |
val stop = |
|
76dd9b9cf624
more robust "stop": further "stamp" ticks may happen afterwards;
wenzelm
parents:
78242
diff
changeset
|
129 |
db.execute_query_statementO( |
|
76dd9b9cf624
more robust "stop": further "stamp" ticks may happen afterwards;
wenzelm
parents:
78242
diff
changeset
|
130 |
Agents.table.select(List(Agents.stop), sql = sql), _.get_date(Agents.stop)).flatten |
|
76dd9b9cf624
more robust "stop": further "stamp" ticks may happen afterwards;
wenzelm
parents:
78242
diff
changeset
|
131 |
|
|
76dd9b9cf624
more robust "stop": further "stamp" ticks may happen afterwards;
wenzelm
parents:
78242
diff
changeset
|
132 |
db.execute_statement( |
|
76dd9b9cf624
more robust "stop": further "stamp" ticks may happen afterwards;
wenzelm
parents:
78242
diff
changeset
|
133 |
Agents.table.update(List(Agents.stamp, Agents.stop, Agents.seen), sql = sql), |
|
76dd9b9cf624
more robust "stop": further "stamp" ticks may happen afterwards;
wenzelm
parents:
78242
diff
changeset
|
134 |
body = { stmt =>
|
|
76dd9b9cf624
more robust "stop": further "stamp" ticks may happen afterwards;
wenzelm
parents:
78242
diff
changeset
|
135 |
val now = db.now() |
|
76dd9b9cf624
more robust "stop": further "stamp" ticks may happen afterwards;
wenzelm
parents:
78242
diff
changeset
|
136 |
stmt.date(1) = now |
|
76dd9b9cf624
more robust "stop": further "stamp" ticks may happen afterwards;
wenzelm
parents:
78242
diff
changeset
|
137 |
stmt.date(2) = if (stop_now) Some(now) else stop |
|
76dd9b9cf624
more robust "stop": further "stamp" ticks may happen afterwards;
wenzelm
parents:
78242
diff
changeset
|
138 |
stmt.long(3) = seen |
|
76dd9b9cf624
more robust "stop": further "stamp" ticks may happen afterwards;
wenzelm
parents:
78242
diff
changeset
|
139 |
}) |
| 78155 | 140 |
} |
141 |
||
|
78535
af37e1b4dce0
more scalable Database_Progress via asynchronous Consumer_Thread.fork_bulk;
wenzelm
parents:
78532
diff
changeset
|
142 |
def read_messages_serial(db: SQL.Database, context: Long): Long = |
| 78155 | 143 |
db.execute_query_statementO( |
144 |
Messages.table.select( |
|
145 |
List(Messages.serial.max), sql = Base.context.where_equal(context)), |
|
146 |
_.long(Messages.serial) |
|
|
78535
af37e1b4dce0
more scalable Database_Progress via asynchronous Consumer_Thread.fork_bulk;
wenzelm
parents:
78532
diff
changeset
|
147 |
).getOrElse(0L) |
| 78155 | 148 |
|
149 |
def read_messages(db: SQL.Database, context: Long, seen: Long = 0): Messages.T = |
|
150 |
db.execute_query_statement( |
|
151 |
Messages.table.select( |
|
152 |
List(Messages.serial, Messages.kind, Messages.text, Messages.verbose), |
|
153 |
sql = |
|
154 |
SQL.where_and( |
|
155 |
Messages.context.ident + " = " + context, |
|
156 |
if (seen <= 0) "" else Messages.serial.ident + " > " + seen)), |
|
157 |
SortedMap.from[Long, Message], |
|
158 |
{ res =>
|
|
159 |
val serial = res.long(Messages.serial) |
|
| 78611 | 160 |
val kind = Kind.fromOrdinal(res.int(Messages.kind)) |
| 78155 | 161 |
val text = res.string(Messages.text) |
162 |
val verbose = res.bool(Messages.verbose) |
|
163 |
serial -> Message(kind, text, verbose = verbose) |
|
164 |
} |
|
165 |
) |
|
166 |
||
167 |
def write_messages( |
|
168 |
db: SQL.Database, |
|
169 |
context: Long, |
|
|
78539
15f55d02ba67
more scalable write_messages via db.execute_batch_statement;
wenzelm
parents:
78537
diff
changeset
|
170 |
messages: List[(Long, Message)] |
| 78155 | 171 |
): Unit = {
|
|
78551
d0c9d277620e
clarified signature: more robust treatment of implicit state;
wenzelm
parents:
78550
diff
changeset
|
172 |
db.execute_batch_statement(Messages.table.insert(), batch = |
|
d0c9d277620e
clarified signature: more robust treatment of implicit state;
wenzelm
parents:
78550
diff
changeset
|
173 |
for ((serial, message) <- messages) yield { (stmt: SQL.Statement) =>
|
|
78539
15f55d02ba67
more scalable write_messages via db.execute_batch_statement;
wenzelm
parents:
78537
diff
changeset
|
174 |
stmt.long(1) = context |
|
15f55d02ba67
more scalable write_messages via db.execute_batch_statement;
wenzelm
parents:
78537
diff
changeset
|
175 |
stmt.long(2) = serial |
| 78611 | 176 |
stmt.int(3) = message.kind.ordinal |
|
78539
15f55d02ba67
more scalable write_messages via db.execute_batch_statement;
wenzelm
parents:
78537
diff
changeset
|
177 |
stmt.string(4) = message.text |
|
15f55d02ba67
more scalable write_messages via db.execute_batch_statement;
wenzelm
parents:
78537
diff
changeset
|
178 |
stmt.bool(5) = message.verbose |
|
78551
d0c9d277620e
clarified signature: more robust treatment of implicit state;
wenzelm
parents:
78550
diff
changeset
|
179 |
}) |
| 78155 | 180 |
} |
181 |
} |
|
|
68410
4e27f5c361d2
clarified signature: more uniform theory_message (see also d7920eb7de54);
wenzelm
parents:
68330
diff
changeset
|
182 |
} |
|
4e27f5c361d2
clarified signature: more uniform theory_message (see also d7920eb7de54);
wenzelm
parents:
68330
diff
changeset
|
183 |
|
| 75393 | 184 |
class Progress {
|
| 78876 | 185 |
def now(): Date = Date.now() |
186 |
val start: Date = now() |
|
187 |
||
|
77509
3bc49507bae5
clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents:
77507
diff
changeset
|
188 |
def verbose: Boolean = false |
|
3bc49507bae5
clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents:
77507
diff
changeset
|
189 |
final def do_output(message: Progress.Message): Boolean = !message.verbose || verbose |
|
3bc49507bae5
clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents:
77507
diff
changeset
|
190 |
|
| 78432 | 191 |
def output(message: Progress.Message): Unit = {}
|
|
77502
2e2b2bd6b2d2
clarified signature: require just one "override def echo(message: Progress.Message): Unit";
wenzelm
parents:
77499
diff
changeset
|
192 |
|
|
77509
3bc49507bae5
clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents:
77507
diff
changeset
|
193 |
final def echo(msg: String, verbose: Boolean = false): Unit = |
|
3bc49507bae5
clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents:
77507
diff
changeset
|
194 |
output(Progress.Message(Progress.Kind.writeln, msg, verbose = verbose)) |
|
3bc49507bae5
clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents:
77507
diff
changeset
|
195 |
final def echo_warning(msg: String, verbose: Boolean = false): Unit = |
|
3bc49507bae5
clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents:
77507
diff
changeset
|
196 |
output(Progress.Message(Progress.Kind.warning, msg, verbose = verbose)) |
|
3bc49507bae5
clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents:
77507
diff
changeset
|
197 |
final def echo_error_message(msg: String, verbose: Boolean = false): Unit = |
|
3bc49507bae5
clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents:
77507
diff
changeset
|
198 |
output(Progress.Message(Progress.Kind.error_message, msg, verbose = verbose)) |
|
77502
2e2b2bd6b2d2
clarified signature: require just one "override def echo(message: Progress.Message): Unit";
wenzelm
parents:
77499
diff
changeset
|
199 |
|
|
77506
a8175b950173
more robust signature: avoid totally adhoc overriding (see also Build_Process.progress vs. build_progress);
wenzelm
parents:
77504
diff
changeset
|
200 |
final def echo_if(cond: Boolean, msg: String): Unit = if (cond) echo(msg) |
|
77499
8fc94efa954a
clarified signature: more uniform Progress.verbose, avoid adhoc "override def theory()";
wenzelm
parents:
77498
diff
changeset
|
201 |
|
|
77509
3bc49507bae5
clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents:
77507
diff
changeset
|
202 |
def theory(theory: Progress.Theory): Unit = output(theory.message) |
| 73340 | 203 |
def nodes_status(nodes_status: Document_Status.Nodes_Status): Unit = {}
|
| 64909 | 204 |
|
| 78432 | 205 |
final def capture[A](e: => A, msg: String, err: Throwable => String): Exn.Result[A] = {
|
206 |
echo(msg) |
|
207 |
try { Exn.Res(e) }
|
|
208 |
catch { case exn: Throwable => echo_error_message(err(exn)); Exn.Exn[A](exn) }
|
|
209 |
} |
|
210 |
||
|
77506
a8175b950173
more robust signature: avoid totally adhoc overriding (see also Build_Process.progress vs. build_progress);
wenzelm
parents:
77504
diff
changeset
|
211 |
final def timeit[A]( |
|
a8175b950173
more robust signature: avoid totally adhoc overriding (see also Build_Process.progress vs. build_progress);
wenzelm
parents:
77504
diff
changeset
|
212 |
body: => A, |
|
a8175b950173
more robust signature: avoid totally adhoc overriding (see also Build_Process.progress vs. build_progress);
wenzelm
parents:
77504
diff
changeset
|
213 |
message: Exn.Result[A] => String = null, |
|
a8175b950173
more robust signature: avoid totally adhoc overriding (see also Build_Process.progress vs. build_progress);
wenzelm
parents:
77504
diff
changeset
|
214 |
enabled: Boolean = true |
|
77509
3bc49507bae5
clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents:
77507
diff
changeset
|
215 |
): A = Timing.timeit(body, message = message, enabled = enabled, output = echo(_)) |
| 65921 | 216 |
|
| 77524 | 217 |
@volatile private var is_stopped = false |
| 73367 | 218 |
def stop(): Unit = { is_stopped = true }
|
| 75393 | 219 |
def stopped: Boolean = {
|
| 73367 | 220 |
if (Thread.interrupted()) is_stopped = true |
|
71726
a5fda30edae2
clarified signature: more uniform treatment of stopped/interrupted state;
wenzelm
parents:
71601
diff
changeset
|
221 |
is_stopped |
|
a5fda30edae2
clarified signature: more uniform treatment of stopped/interrupted state;
wenzelm
parents:
71601
diff
changeset
|
222 |
} |
|
78529
0e79fa88cab6
build_worker is stopped independently from master build_process;
wenzelm
parents:
78505
diff
changeset
|
223 |
def stopped_local: Boolean = false |
|
71726
a5fda30edae2
clarified signature: more uniform treatment of stopped/interrupted state;
wenzelm
parents:
71601
diff
changeset
|
224 |
|
|
77506
a8175b950173
more robust signature: avoid totally adhoc overriding (see also Build_Process.progress vs. build_progress);
wenzelm
parents:
77504
diff
changeset
|
225 |
final def interrupt_handler[A](e: => A): A = POSIX_Interrupt.handler { stop() } { e }
|
|
a8175b950173
more robust signature: avoid totally adhoc overriding (see also Build_Process.progress vs. build_progress);
wenzelm
parents:
77504
diff
changeset
|
226 |
final def expose_interrupt(): Unit = if (stopped) throw Exn.Interrupt() |
| 61276 | 227 |
override def toString: String = if (stopped) "Progress(stopped)" else "Progress" |
| 64201 | 228 |
|
|
77506
a8175b950173
more robust signature: avoid totally adhoc overriding (see also Build_Process.progress vs. build_progress);
wenzelm
parents:
77504
diff
changeset
|
229 |
final def bash(script: String, |
| 64201 | 230 |
cwd: JFile = null, |
| 73897 | 231 |
env: JMap[String, String] = Isabelle_System.settings(), |
| 64201 | 232 |
redirect: Boolean = false, |
| 65930 | 233 |
echo: Boolean = false, |
| 72599 | 234 |
watchdog: Time = Time.zero, |
| 75393 | 235 |
strict: Boolean = true |
236 |
): Process_Result = {
|
|
| 72599 | 237 |
val result = |
238 |
Isabelle_System.bash(script, cwd = cwd, env = env, redirect = redirect, |
|
239 |
progress_stdout = echo_if(echo, _), |
|
240 |
progress_stderr = echo_if(echo, _), |
|
241 |
watchdog = if (watchdog.is_zero) None else Some((watchdog, _ => stopped)), |
|
242 |
strict = strict) |
|
243 |
if (strict && stopped) throw Exn.Interrupt() else result |
|
| 64201 | 244 |
} |
| 61276 | 245 |
} |
246 |
||
|
77499
8fc94efa954a
clarified signature: more uniform Progress.verbose, avoid adhoc "override def theory()";
wenzelm
parents:
77498
diff
changeset
|
247 |
class Console_Progress(override val verbose: Boolean = false, stderr: Boolean = false) |
|
8fc94efa954a
clarified signature: more uniform Progress.verbose, avoid adhoc "override def theory()";
wenzelm
parents:
77498
diff
changeset
|
248 |
extends Progress {
|
| 78874 | 249 |
override def output(message: Progress.Message): Unit = synchronized {
|
|
77509
3bc49507bae5
clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents:
77507
diff
changeset
|
250 |
if (do_output(message)) {
|
|
3bc49507bae5
clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents:
77507
diff
changeset
|
251 |
Output.output(message.output_text, stdout = !stderr, include_empty = true) |
|
3bc49507bae5
clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents:
77507
diff
changeset
|
252 |
} |
| 78874 | 253 |
} |
| 77503 | 254 |
|
255 |
override def toString: String = super.toString + ": console" |
|
| 61276 | 256 |
} |
| 65888 | 257 |
|
| 77507 | 258 |
class File_Progress(path: Path, override val verbose: Boolean = false) |
259 |
extends Progress {
|
|
| 78874 | 260 |
override def output(message: Progress.Message): Unit = synchronized {
|
|
77509
3bc49507bae5
clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents:
77507
diff
changeset
|
261 |
if (do_output(message)) File.append(path, message.output_text + "\n") |
| 78874 | 262 |
} |
| 65888 | 263 |
|
| 77503 | 264 |
override def toString: String = super.toString + ": " + path.toString |
| 65888 | 265 |
} |
|
76994
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
266 |
|
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
267 |
|
| 78155 | 268 |
/* database progress */ |
269 |
||
270 |
class Database_Progress( |
|
| 78532 | 271 |
db: SQL.Database, |
272 |
base_progress: Progress, |
|
|
78536
555bdac7c279
restrict input_messages to master build_process: avoid excessive db traffic for distributed build_workers;
wenzelm
parents:
78535
diff
changeset
|
273 |
input_messages: Boolean = false, |
| 78532 | 274 |
output_stopped: Boolean = false, |
275 |
kind: String = "progress", |
|
276 |
hostname: String = Isabelle_System.hostname(), |
|
|
78535
af37e1b4dce0
more scalable Database_Progress via asynchronous Consumer_Thread.fork_bulk;
wenzelm
parents:
78532
diff
changeset
|
277 |
context_uuid: String = UUID.random().toString, |
|
af37e1b4dce0
more scalable Database_Progress via asynchronous Consumer_Thread.fork_bulk;
wenzelm
parents:
78532
diff
changeset
|
278 |
timeout: Option[Time] = None) |
| 78155 | 279 |
extends Progress {
|
280 |
database_progress => |
|
281 |
||
| 78876 | 282 |
override def now(): Date = db.now() |
283 |
override val start: Date = now() |
|
284 |
||
| 78537 | 285 |
if (UUID.unapply(context_uuid).isEmpty) {
|
286 |
error("Bad Database_Progress.context_uuid: " + quote(context_uuid))
|
|
287 |
} |
|
288 |
||
| 78155 | 289 |
private var _agent_uuid: String = "" |
| 78382 | 290 |
private var _context: Long = -1 |
| 78504 | 291 |
private var _serial: Long = 0 |
|
78529
0e79fa88cab6
build_worker is stopped independently from master build_process;
wenzelm
parents:
78505
diff
changeset
|
292 |
private var _stopped_db: Boolean = false |
|
78535
af37e1b4dce0
more scalable Database_Progress via asynchronous Consumer_Thread.fork_bulk;
wenzelm
parents:
78532
diff
changeset
|
293 |
private var _consumer: Consumer_Thread[Progress.Output] = null |
| 78155 | 294 |
|
295 |
def agent_uuid: String = synchronized { _agent_uuid }
|
|
296 |
||
297 |
private def init(): Unit = synchronized {
|
|
|
78396
7853d9072d1b
renamed object Data to private_data, to emphasize its intended scope (but it is publicly accessible in the database);
wenzelm
parents:
78389
diff
changeset
|
298 |
Progress.private_data.transaction_lock(db, create = true, label = "Database_Progress.init") {
|
|
7853d9072d1b
renamed object Data to private_data, to emphasize its intended scope (but it is publicly accessible in the database);
wenzelm
parents:
78389
diff
changeset
|
299 |
Progress.private_data.read_progress_context(db, context_uuid) match {
|
| 78155 | 300 |
case Some(context) => |
301 |
_context = context |
|
302 |
_agent_uuid = UUID.random().toString |
|
303 |
case None => |
|
|
78396
7853d9072d1b
renamed object Data to private_data, to emphasize its intended scope (but it is publicly accessible in the database);
wenzelm
parents:
78389
diff
changeset
|
304 |
_context = Progress.private_data.next_progress_context(db) |
| 78155 | 305 |
_agent_uuid = context_uuid |
|
78396
7853d9072d1b
renamed object Data to private_data, to emphasize its intended scope (but it is publicly accessible in the database);
wenzelm
parents:
78389
diff
changeset
|
306 |
db.execute_statement(Progress.private_data.Base.table.insert(), { stmt =>
|
| 78155 | 307 |
stmt.string(1) = context_uuid |
308 |
stmt.long(2) = _context |
|
309 |
stmt.bool(3) = false |
|
310 |
}) |
|
311 |
} |
|
|
78396
7853d9072d1b
renamed object Data to private_data, to emphasize its intended scope (but it is publicly accessible in the database);
wenzelm
parents:
78389
diff
changeset
|
312 |
db.execute_statement(Progress.private_data.Agents.table.insert(), { stmt =>
|
| 78155 | 313 |
val java = ProcessHandle.current() |
314 |
val java_pid = java.pid |
|
315 |
val java_start = Date.instant(java.info.startInstant.get) |
|
316 |
||
317 |
stmt.string(1) = _agent_uuid |
|
318 |
stmt.string(2) = context_uuid |
|
| 78240 | 319 |
stmt.string(3) = kind |
320 |
stmt.string(4) = hostname |
|
321 |
stmt.long(5) = java_pid |
|
322 |
stmt.date(6) = java_start |
|
| 78876 | 323 |
stmt.date(7) = start |
324 |
stmt.date(8) = start |
|
| 78240 | 325 |
stmt.date(9) = None |
326 |
stmt.long(10) = 0L |
|
| 78155 | 327 |
}) |
|
78187
2df0f3604a67
clarified signature: more explicit class SQL.Data;
wenzelm
parents:
78170
diff
changeset
|
328 |
} |
|
78396
7853d9072d1b
renamed object Data to private_data, to emphasize its intended scope (but it is publicly accessible in the database);
wenzelm
parents:
78389
diff
changeset
|
329 |
if (context_uuid == _agent_uuid) db.vacuum(Progress.private_data.tables.list) |
|
78535
af37e1b4dce0
more scalable Database_Progress via asynchronous Consumer_Thread.fork_bulk;
wenzelm
parents:
78532
diff
changeset
|
330 |
|
| 78564 | 331 |
def consume(bulk_output: List[Progress.Output]): List[Exn.Result[Unit]] = sync_database {
|
332 |
if (bulk_output.nonEmpty) {
|
|
333 |
for (out <- bulk_output) {
|
|
334 |
out match {
|
|
335 |
case message: Progress.Message => |
|
336 |
if (do_output(message)) base_progress.output(message) |
|
337 |
case theory: Progress.Theory => base_progress.theory(theory) |
|
338 |
} |
|
339 |
} |
|
340 |
||
341 |
val messages = |
|
342 |
for ((out, i) <- bulk_output.zipWithIndex) |
|
343 |
yield (_serial + i + 1) -> out.message |
|
344 |
||
345 |
Progress.private_data.write_messages(db, _context, messages) |
|
346 |
_serial = messages.last._1 |
|
347 |
} |
|
348 |
bulk_output.map(_ => Exn.Res(())) |
|
349 |
} |
|
350 |
||
|
78535
af37e1b4dce0
more scalable Database_Progress via asynchronous Consumer_Thread.fork_bulk;
wenzelm
parents:
78532
diff
changeset
|
351 |
_consumer = Consumer_Thread.fork_bulk[Progress.Output](name = "Database_Progress.consumer")( |
|
af37e1b4dce0
more scalable Database_Progress via asynchronous Consumer_Thread.fork_bulk;
wenzelm
parents:
78532
diff
changeset
|
352 |
bulk = _ => true, timeout = timeout, |
| 78565 | 353 |
consume = { bulk_output =>
|
354 |
val results = |
|
355 |
if (bulk_output.isEmpty) consume(Nil) |
|
356 |
else bulk_output.grouped(200).toList.flatMap(consume) |
|
357 |
(results, true) }) |
|
| 78155 | 358 |
} |
359 |
||
| 78242 | 360 |
def exit(close: Boolean = false): Unit = synchronized {
|
| 78155 | 361 |
if (_context > 0) {
|
|
78535
af37e1b4dce0
more scalable Database_Progress via asynchronous Consumer_Thread.fork_bulk;
wenzelm
parents:
78532
diff
changeset
|
362 |
_consumer.shutdown() |
|
af37e1b4dce0
more scalable Database_Progress via asynchronous Consumer_Thread.fork_bulk;
wenzelm
parents:
78532
diff
changeset
|
363 |
_consumer = null |
|
af37e1b4dce0
more scalable Database_Progress via asynchronous Consumer_Thread.fork_bulk;
wenzelm
parents:
78532
diff
changeset
|
364 |
|
|
78396
7853d9072d1b
renamed object Data to private_data, to emphasize its intended scope (but it is publicly accessible in the database);
wenzelm
parents:
78389
diff
changeset
|
365 |
Progress.private_data.transaction_lock(db, label = "Database_Progress.exit") {
|
| 78504 | 366 |
Progress.private_data.update_agent(db, _agent_uuid, _serial, stop_now = true) |
| 78155 | 367 |
} |
368 |
_context = 0 |
|
369 |
} |
|
| 78242 | 370 |
if (close) db.close() |
| 78155 | 371 |
} |
372 |
||
|
78535
af37e1b4dce0
more scalable Database_Progress via asynchronous Consumer_Thread.fork_bulk;
wenzelm
parents:
78532
diff
changeset
|
373 |
private def sync_context[A](body: => A): A = synchronized {
|
| 78382 | 374 |
if (_context < 0) throw new IllegalStateException("Database_Progress before init")
|
375 |
if (_context == 0) throw new IllegalStateException("Database_Progress after exit")
|
|
376 |
||
|
78535
af37e1b4dce0
more scalable Database_Progress via asynchronous Consumer_Thread.fork_bulk;
wenzelm
parents:
78532
diff
changeset
|
377 |
body |
|
af37e1b4dce0
more scalable Database_Progress via asynchronous Consumer_Thread.fork_bulk;
wenzelm
parents:
78532
diff
changeset
|
378 |
} |
|
af37e1b4dce0
more scalable Database_Progress via asynchronous Consumer_Thread.fork_bulk;
wenzelm
parents:
78532
diff
changeset
|
379 |
|
| 78586 | 380 |
private def sync_database[A](body: => A): A = synchronized {
|
| 78549 | 381 |
Progress.private_data.transaction_lock(db, label = "Database_Progress.sync_database") {
|
|
78529
0e79fa88cab6
build_worker is stopped independently from master build_process;
wenzelm
parents:
78505
diff
changeset
|
382 |
_stopped_db = Progress.private_data.read_progress_stopped(db, _context) |
| 78155 | 383 |
|
|
78529
0e79fa88cab6
build_worker is stopped independently from master build_process;
wenzelm
parents:
78505
diff
changeset
|
384 |
if (_stopped_db && !base_progress.stopped) base_progress.stop() |
|
0e79fa88cab6
build_worker is stopped independently from master build_process;
wenzelm
parents:
78505
diff
changeset
|
385 |
if (!_stopped_db && base_progress.stopped && output_stopped) {
|
|
0e79fa88cab6
build_worker is stopped independently from master build_process;
wenzelm
parents:
78505
diff
changeset
|
386 |
Progress.private_data.write_progress_stopped(db, _context, true) |
|
0e79fa88cab6
build_worker is stopped independently from master build_process;
wenzelm
parents:
78505
diff
changeset
|
387 |
} |
| 78155 | 388 |
|
|
78536
555bdac7c279
restrict input_messages to master build_process: avoid excessive db traffic for distributed build_workers;
wenzelm
parents:
78535
diff
changeset
|
389 |
val serial0 = _serial |
|
555bdac7c279
restrict input_messages to master build_process: avoid excessive db traffic for distributed build_workers;
wenzelm
parents:
78535
diff
changeset
|
390 |
if (input_messages) {
|
|
555bdac7c279
restrict input_messages to master build_process: avoid excessive db traffic for distributed build_workers;
wenzelm
parents:
78535
diff
changeset
|
391 |
val messages = Progress.private_data.read_messages(db, _context, seen = _serial) |
|
555bdac7c279
restrict input_messages to master build_process: avoid excessive db traffic for distributed build_workers;
wenzelm
parents:
78535
diff
changeset
|
392 |
for ((message_serial, message) <- messages) {
|
|
555bdac7c279
restrict input_messages to master build_process: avoid excessive db traffic for distributed build_workers;
wenzelm
parents:
78535
diff
changeset
|
393 |
if (base_progress.do_output(message)) base_progress.output(message) |
|
555bdac7c279
restrict input_messages to master build_process: avoid excessive db traffic for distributed build_workers;
wenzelm
parents:
78535
diff
changeset
|
394 |
_serial = _serial max message_serial |
|
555bdac7c279
restrict input_messages to master build_process: avoid excessive db traffic for distributed build_workers;
wenzelm
parents:
78535
diff
changeset
|
395 |
} |
| 78155 | 396 |
} |
|
78536
555bdac7c279
restrict input_messages to master build_process: avoid excessive db traffic for distributed build_workers;
wenzelm
parents:
78535
diff
changeset
|
397 |
else {
|
|
555bdac7c279
restrict input_messages to master build_process: avoid excessive db traffic for distributed build_workers;
wenzelm
parents:
78535
diff
changeset
|
398 |
_serial = _serial max Progress.private_data.read_messages_serial(db, _context) |
|
555bdac7c279
restrict input_messages to master build_process: avoid excessive db traffic for distributed build_workers;
wenzelm
parents:
78535
diff
changeset
|
399 |
} |
|
555bdac7c279
restrict input_messages to master build_process: avoid excessive db traffic for distributed build_workers;
wenzelm
parents:
78535
diff
changeset
|
400 |
|
|
78550
d8cc0f625b52
proper sync_database for Database_Progress consumer;
wenzelm
parents:
78549
diff
changeset
|
401 |
val res = body |
|
d8cc0f625b52
proper sync_database for Database_Progress consumer;
wenzelm
parents:
78549
diff
changeset
|
402 |
|
|
78536
555bdac7c279
restrict input_messages to master build_process: avoid excessive db traffic for distributed build_workers;
wenzelm
parents:
78535
diff
changeset
|
403 |
if (_serial != serial0) Progress.private_data.update_agent(db, _agent_uuid, _serial) |
| 78155 | 404 |
|
|
78550
d8cc0f625b52
proper sync_database for Database_Progress consumer;
wenzelm
parents:
78549
diff
changeset
|
405 |
res |
| 78155 | 406 |
} |
407 |
} |
|
408 |
||
|
78535
af37e1b4dce0
more scalable Database_Progress via asynchronous Consumer_Thread.fork_bulk;
wenzelm
parents:
78532
diff
changeset
|
409 |
private def sync(): Unit = sync_database {}
|
| 78155 | 410 |
|
|
78535
af37e1b4dce0
more scalable Database_Progress via asynchronous Consumer_Thread.fork_bulk;
wenzelm
parents:
78532
diff
changeset
|
411 |
override def output(message: Progress.Message): Unit = sync_context { _consumer.send(message) }
|
|
af37e1b4dce0
more scalable Database_Progress via asynchronous Consumer_Thread.fork_bulk;
wenzelm
parents:
78532
diff
changeset
|
412 |
override def theory(theory: Progress.Theory): Unit = sync_context { _consumer.send(theory) }
|
| 78155 | 413 |
|
414 |
override def nodes_status(nodes_status: Document_Status.Nodes_Status): Unit = |
|
415 |
base_progress.nodes_status(nodes_status) |
|
416 |
||
417 |
override def verbose: Boolean = base_progress.verbose |
|
418 |
||
|
78535
af37e1b4dce0
more scalable Database_Progress via asynchronous Consumer_Thread.fork_bulk;
wenzelm
parents:
78532
diff
changeset
|
419 |
override def stop(): Unit = sync_context { base_progress.stop(); sync() }
|
|
78550
d8cc0f625b52
proper sync_database for Database_Progress consumer;
wenzelm
parents:
78549
diff
changeset
|
420 |
override def stopped: Boolean = sync_context { base_progress.stopped }
|
|
d8cc0f625b52
proper sync_database for Database_Progress consumer;
wenzelm
parents:
78549
diff
changeset
|
421 |
override def stopped_local: Boolean = sync_context { base_progress.stopped && !_stopped_db }
|
| 78155 | 422 |
|
423 |
override def toString: String = super.toString + ": database " + db |
|
424 |
||
425 |
init() |
|
426 |
sync() |
|
427 |
} |
|
428 |
||
429 |
||
|
76994
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
430 |
/* structured program progress */ |
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
431 |
|
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
432 |
object Program_Progress {
|
| 77174 | 433 |
class Program private[Program_Progress](heading: String, title: String) {
|
|
76994
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
434 |
private val output_buffer = new StringBuffer(256) // synchronized |
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
435 |
|
|
77509
3bc49507bae5
clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents:
77507
diff
changeset
|
436 |
def output(message: Progress.Message): Unit = synchronized {
|
|
76994
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
437 |
if (output_buffer.length() > 0) output_buffer.append('\n')
|
|
77502
2e2b2bd6b2d2
clarified signature: require just one "override def echo(message: Progress.Message): Unit";
wenzelm
parents:
77499
diff
changeset
|
438 |
output_buffer.append(message.output_text) |
|
76994
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
439 |
} |
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
440 |
|
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
441 |
val start_time: Time = Time.now() |
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
442 |
private var stop_time: Option[Time] = None |
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
443 |
def stop_now(): Unit = synchronized { stop_time = Some(Time.now()) }
|
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
444 |
|
| 77174 | 445 |
def output(): (Command.Results, XML.Body) = synchronized {
|
|
76994
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
446 |
val output_text = output_buffer.toString |
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
447 |
val elapsed_time = stop_time.map(t => t - start_time) |
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
448 |
|
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
449 |
val message_prefix = heading + " " |
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
450 |
val message_suffix = |
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
451 |
elapsed_time match {
|
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
452 |
case None => " ..." |
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
453 |
case Some(t) => " ... (" + t.message + " elapsed time)"
|
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
454 |
} |
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
455 |
|
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
456 |
val (results, message) = |
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
457 |
if (output_text.isEmpty) {
|
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
458 |
(Command.Results.empty, XML.string(message_prefix + title + message_suffix)) |
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
459 |
} |
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
460 |
else {
|
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
461 |
val i = Document_ID.make() |
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
462 |
val results = Command.Results.make(List(i -> Protocol.writeln_message(output_text))) |
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
463 |
val message = |
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
464 |
XML.string(message_prefix) ::: |
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
465 |
List(XML.Elem(Markup(Markup.WRITELN, Markup.Serial(i)), XML.string(title))) ::: |
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
466 |
XML.string(message_suffix) |
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
467 |
(results, message) |
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
468 |
} |
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
469 |
|
| 76997 | 470 |
(results, List(XML.elem(Markup.TRACING_MESSAGE, message))) |
|
76994
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
471 |
} |
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
472 |
} |
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
473 |
} |
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
474 |
|
| 77174 | 475 |
abstract class Program_Progress( |
476 |
default_heading: String = "Running", |
|
|
77499
8fc94efa954a
clarified signature: more uniform Progress.verbose, avoid adhoc "override def theory()";
wenzelm
parents:
77498
diff
changeset
|
477 |
default_title: String = "program", |
|
8fc94efa954a
clarified signature: more uniform Progress.verbose, avoid adhoc "override def theory()";
wenzelm
parents:
77498
diff
changeset
|
478 |
override val verbose: Boolean = false |
| 77174 | 479 |
) extends Progress {
|
|
76994
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
480 |
private var _finished_programs: List[Program_Progress.Program] = Nil |
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
481 |
private var _running_program: Option[Program_Progress.Program] = None |
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
482 |
|
| 77174 | 483 |
def output(): (Command.Results, XML.Body) = synchronized {
|
|
76994
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
484 |
val programs = (_running_program.toList ::: _finished_programs).reverse |
| 77174 | 485 |
val programs_output = programs.map(_.output()) |
|
76994
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
486 |
val results = Command.Results.merge(programs_output.map(_._1)) |
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
487 |
val body = Library.separate(Pretty.Separator, programs_output.map(_._2)).flatten |
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
488 |
(results, body) |
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
489 |
} |
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
490 |
|
| 77174 | 491 |
private def start_program(heading: String, title: String): Unit = synchronized {
|
492 |
_running_program = Some(new Program_Progress.Program(heading, title)) |
|
|
76994
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
493 |
} |
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
494 |
|
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
495 |
def stop_program(): Unit = synchronized {
|
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
496 |
_running_program match {
|
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
497 |
case Some(program) => |
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
498 |
program.stop_now() |
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
499 |
_finished_programs ::= program |
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
500 |
_running_program = None |
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
501 |
case None => |
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
502 |
} |
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
503 |
} |
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
504 |
|
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
505 |
def detect_program(s: String): Option[String] |
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
506 |
|
|
77509
3bc49507bae5
clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents:
77507
diff
changeset
|
507 |
override def output(message: Progress.Message): Unit = synchronized {
|
|
77502
2e2b2bd6b2d2
clarified signature: require just one "override def echo(message: Progress.Message): Unit";
wenzelm
parents:
77499
diff
changeset
|
508 |
val writeln_msg = if (message.kind == Progress.Kind.writeln) message.text else "" |
|
2e2b2bd6b2d2
clarified signature: require just one "override def echo(message: Progress.Message): Unit";
wenzelm
parents:
77499
diff
changeset
|
509 |
detect_program(writeln_msg).map(Word.explode) match {
|
| 77174 | 510 |
case Some(a :: bs) => |
|
76994
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
511 |
stop_program() |
| 77174 | 512 |
start_program(a, Word.implode(bs)) |
513 |
case _ => |
|
514 |
if (_running_program.isEmpty) start_program(default_heading, default_title) |
|
|
77509
3bc49507bae5
clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents:
77507
diff
changeset
|
515 |
if (do_output(message)) _running_program.get.output(message) |
|
76994
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
516 |
} |
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
517 |
} |
|
7c23db6b857b
more detailed Program_Progress / Log_Progress: each program gets its own log output, which is attached to the document via markup;
wenzelm
parents:
76593
diff
changeset
|
518 |
} |