author | wenzelm |
Wed, 24 Sep 2025 22:47:04 +0200 | |
changeset 83229 | ad2b6030cb9c |
parent 83227 | 2ecfd436903b |
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 |
|
12 |
||
75393 | 13 |
object Progress { |
78503 | 14 |
/* output */ |
15 |
||
16 |
sealed abstract class Output { def message: Message } |
|
78155 | 17 |
|
78611 | 18 |
enum Kind { case writeln, warning, error_message } |
78503 | 19 |
sealed case class Message( |
78611 | 20 |
kind: Kind, |
78503 | 21 |
text: String, |
22 |
verbose: Boolean = false |
|
23 |
) extends Output { |
|
24 |
override def message: Message = this |
|
25 |
||
77502
2e2b2bd6b2d2
clarified signature: require just one "override def echo(message: Progress.Message): Unit";
wenzelm
parents:
77499
diff
changeset
|
26 |
def output_text: String = |
2e2b2bd6b2d2
clarified signature: require just one "override def echo(message: Progress.Message): Unit";
wenzelm
parents:
77499
diff
changeset
|
27 |
kind match { |
2e2b2bd6b2d2
clarified signature: require just one "override def echo(message: Progress.Message): Unit";
wenzelm
parents:
77499
diff
changeset
|
28 |
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
|
29 |
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
|
30 |
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
|
31 |
} |
2e2b2bd6b2d2
clarified signature: require just one "override def echo(message: Progress.Message): Unit";
wenzelm
parents:
77499
diff
changeset
|
32 |
|
2e2b2bd6b2d2
clarified signature: require just one "override def echo(message: Progress.Message): Unit";
wenzelm
parents:
77499
diff
changeset
|
33 |
override def toString: String = output_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 |
|
78503 | 36 |
sealed case class Theory( |
37 |
theory: String, |
|
38 |
session: String = "", |
|
83223 | 39 |
percentage: Option[Int] = None, |
40 |
total_time: Time = Time.zero |
|
78503 | 41 |
) extends Output { |
77502
2e2b2bd6b2d2
clarified signature: require just one "override def echo(message: Progress.Message): Unit";
wenzelm
parents:
77499
diff
changeset
|
42 |
def message: Message = |
83223 | 43 |
Message(Kind.writeln, print_session + print_theory + print_percentage + print_total_time, |
44 |
verbose = true) |
|
68987 | 45 |
|
77504 | 46 |
def print_session: String = if_proper(session, session + ": ") |
68987 | 47 |
def print_theory: String = "theory " + theory |
48 |
def print_percentage: String = |
|
49 |
percentage match { case None => "" case Some(p) => " " + p + "%" } |
|
83223 | 50 |
def print_total_time: String = |
51 |
if (total_time.is_relevant) " (" + total_time.message + " elapsed time)" else "" |
|
68957 | 52 |
} |
83214
911fbc338de7
clarified signature: more explicit type Progress.Nodes_Status;
wenzelm
parents:
83205
diff
changeset
|
53 |
|
911fbc338de7
clarified signature: more explicit type Progress.Nodes_Status;
wenzelm
parents:
83205
diff
changeset
|
54 |
sealed case class Nodes_Status( |
911fbc338de7
clarified signature: more explicit type Progress.Nodes_Status;
wenzelm
parents:
83205
diff
changeset
|
55 |
domain: List[Document.Node.Name], |
83223 | 56 |
document_status: Document_Status.Nodes_Status, |
83227 | 57 |
session: String = "", |
58 |
old: Option[Document_Status.Nodes_Status] = None |
|
83214
911fbc338de7
clarified signature: more explicit type Progress.Nodes_Status;
wenzelm
parents:
83205
diff
changeset
|
59 |
) { |
83223 | 60 |
def message: Message = |
61 |
Message(Kind.writeln, cat_lines(domain.map(name => theory(name).message.text)), |
|
62 |
verbose = true) |
|
63 |
||
64 |
def apply(name: Document.Node.Name): Document_Status.Node_Status = |
|
65 |
document_status(name) |
|
66 |
||
67 |
def theory(name: Document.Node.Name): Theory = { |
|
68 |
val node_status = apply(name) |
|
83229 | 69 |
Theory(theory = name.theory, session = session, |
70 |
percentage = Some(node_status.percentage), |
|
71 |
total_time = node_status.total_timing.elapsed) |
|
83223 | 72 |
} |
83214
911fbc338de7
clarified signature: more explicit type Progress.Nodes_Status;
wenzelm
parents:
83205
diff
changeset
|
73 |
} |
68410
4e27f5c361d2
clarified signature: more uniform theory_message (see also d7920eb7de54);
wenzelm
parents:
68330
diff
changeset
|
74 |
} |
4e27f5c361d2
clarified signature: more uniform theory_message (see also d7920eb7de54);
wenzelm
parents:
68330
diff
changeset
|
75 |
|
75393 | 76 |
class Progress { |
78876 | 77 |
def now(): Date = Date.now() |
78 |
val start: Date = now() |
|
79 |
||
77509
3bc49507bae5
clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents:
77507
diff
changeset
|
80 |
def verbose: Boolean = false |
3bc49507bae5
clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents:
77507
diff
changeset
|
81 |
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
|
82 |
|
78432 | 83 |
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
|
84 |
|
77509
3bc49507bae5
clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents:
77507
diff
changeset
|
85 |
final def echo(msg: String, verbose: Boolean = false): Unit = |
3bc49507bae5
clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents:
77507
diff
changeset
|
86 |
output(Progress.Message(Progress.Kind.writeln, msg, verbose = verbose)) |
3bc49507bae5
clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents:
77507
diff
changeset
|
87 |
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
|
88 |
output(Progress.Message(Progress.Kind.warning, msg, verbose = verbose)) |
3bc49507bae5
clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents:
77507
diff
changeset
|
89 |
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
|
90 |
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
|
91 |
|
77506
a8175b950173
more robust signature: avoid totally adhoc overriding (see also Build_Process.progress vs. build_progress);
wenzelm
parents:
77504
diff
changeset
|
92 |
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
|
93 |
|
77509
3bc49507bae5
clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents:
77507
diff
changeset
|
94 |
def theory(theory: Progress.Theory): Unit = output(theory.message) |
83214
911fbc338de7
clarified signature: more explicit type Progress.Nodes_Status;
wenzelm
parents:
83205
diff
changeset
|
95 |
def nodes_status(nodes_status: Progress.Nodes_Status): Unit = {} |
64909 | 96 |
|
78432 | 97 |
final def capture[A](e: => A, msg: String, err: Throwable => String): Exn.Result[A] = { |
98 |
echo(msg) |
|
99 |
try { Exn.Res(e) } |
|
100 |
catch { case exn: Throwable => echo_error_message(err(exn)); Exn.Exn[A](exn) } |
|
101 |
} |
|
102 |
||
77506
a8175b950173
more robust signature: avoid totally adhoc overriding (see also Build_Process.progress vs. build_progress);
wenzelm
parents:
77504
diff
changeset
|
103 |
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
|
104 |
body: => A, |
a8175b950173
more robust signature: avoid totally adhoc overriding (see also Build_Process.progress vs. build_progress);
wenzelm
parents:
77504
diff
changeset
|
105 |
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
|
106 |
enabled: Boolean = true |
77509
3bc49507bae5
clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents:
77507
diff
changeset
|
107 |
): A = Timing.timeit(body, message = message, enabled = enabled, output = echo(_)) |
65921 | 108 |
|
77524 | 109 |
@volatile private var is_stopped = false |
73367 | 110 |
def stop(): Unit = { is_stopped = true } |
75393 | 111 |
def stopped: Boolean = { |
73367 | 112 |
if (Thread.interrupted()) is_stopped = true |
71726
a5fda30edae2
clarified signature: more uniform treatment of stopped/interrupted state;
wenzelm
parents:
71601
diff
changeset
|
113 |
is_stopped |
a5fda30edae2
clarified signature: more uniform treatment of stopped/interrupted state;
wenzelm
parents:
71601
diff
changeset
|
114 |
} |
a5fda30edae2
clarified signature: more uniform treatment of stopped/interrupted state;
wenzelm
parents:
71601
diff
changeset
|
115 |
|
77506
a8175b950173
more robust signature: avoid totally adhoc overriding (see also Build_Process.progress vs. build_progress);
wenzelm
parents:
77504
diff
changeset
|
116 |
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
|
117 |
final def expose_interrupt(): Unit = if (stopped) throw Exn.Interrupt() |
61276 | 118 |
override def toString: String = if (stopped) "Progress(stopped)" else "Progress" |
64201 | 119 |
|
77506
a8175b950173
more robust signature: avoid totally adhoc overriding (see also Build_Process.progress vs. build_progress);
wenzelm
parents:
77504
diff
changeset
|
120 |
final def bash(script: String, |
80230 | 121 |
ssh: SSH.System = SSH.Local, |
80224
db92e0b6a11a
clarified signature: prefer symbolic isabelle.Path over physical java.io.File;
wenzelm
parents:
79887
diff
changeset
|
122 |
cwd: Path = Path.current, |
82706 | 123 |
env: JMap[String, String] = Isabelle_System.Settings.env(), // ignored for remote ssh |
64201 | 124 |
redirect: Boolean = false, |
65930 | 125 |
echo: Boolean = false, |
80236 | 126 |
watchdog_time: Time = Time.zero, |
75393 | 127 |
strict: Boolean = true |
128 |
): Process_Result = { |
|
72599 | 129 |
val result = |
80230 | 130 |
Isabelle_System.bash(script, ssh = ssh, cwd = cwd, env = env, redirect = redirect, |
72599 | 131 |
progress_stdout = echo_if(echo, _), |
132 |
progress_stderr = echo_if(echo, _), |
|
80236 | 133 |
watchdog = Bash.Watchdog(watchdog_time, _ => stopped), |
72599 | 134 |
strict = strict) |
135 |
if (strict && stopped) throw Exn.Interrupt() else result |
|
64201 | 136 |
} |
61276 | 137 |
} |
138 |
||
77499
8fc94efa954a
clarified signature: more uniform Progress.verbose, avoid adhoc "override def theory()";
wenzelm
parents:
77498
diff
changeset
|
139 |
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
|
140 |
extends Progress { |
78874 | 141 |
override def output(message: Progress.Message): Unit = synchronized { |
77509
3bc49507bae5
clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents:
77507
diff
changeset
|
142 |
if (do_output(message)) { |
3bc49507bae5
clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents:
77507
diff
changeset
|
143 |
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
|
144 |
} |
78874 | 145 |
} |
77503 | 146 |
|
147 |
override def toString: String = super.toString + ": console" |
|
61276 | 148 |
} |
65888 | 149 |
|
77507 | 150 |
class File_Progress(path: Path, override val verbose: Boolean = false) |
151 |
extends Progress { |
|
78874 | 152 |
override def output(message: Progress.Message): Unit = synchronized { |
77509
3bc49507bae5
clarified treatment of "verbose" messages, e.g. Progress.theory();
wenzelm
parents:
77507
diff
changeset
|
153 |
if (do_output(message)) File.append(path, message.output_text + "\n") |
78874 | 154 |
} |
65888 | 155 |
|
77503 | 156 |
override def toString: String = super.toString + ": " + path.toString |
65888 | 157 |
} |