| author | wenzelm | 
| Tue, 03 Sep 2019 11:32:29 +0200 | |
| changeset 70644 | b23a6dfcfd57 | 
| parent 70640 | 5f4b8a505090 | 
| child 70647 | 3047b7671279 | 
| permissions | -rw-r--r-- | 
| 69012 | 1  | 
/* Title: Pure/PIDE/headless.scala  | 
| 67054 | 2  | 
Author: Makarius  | 
3  | 
||
| 69012 | 4  | 
Headless PIDE session and resources from file-system.  | 
| 67054 | 5  | 
*/  | 
6  | 
||
7  | 
package isabelle  | 
|
8  | 
||
9  | 
||
| 67925 | 10  | 
import java.io.{File => JFile}
 | 
11  | 
||
| 
68936
 
90c08c7bab9c
continuously clean frontier of already committed theories: much less resource requirements;
 
wenzelm 
parents: 
68935 
diff
changeset
 | 
12  | 
import scala.annotation.tailrec  | 
| 
69562
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
13  | 
import scala.collection.mutable  | 
| 
68936
 
90c08c7bab9c
continuously clean frontier of already committed theories: much less resource requirements;
 
wenzelm 
parents: 
68935 
diff
changeset
 | 
14  | 
|
| 67925 | 15  | 
|
| 69012 | 16  | 
object Headless  | 
| 67054 | 17  | 
{
 | 
| 69012 | 18  | 
/** session **/  | 
| 
67061
 
2efa25302f34
synchronous session start (similar to isabelle.vscode.Server);
 
wenzelm 
parents: 
67059 
diff
changeset
 | 
19  | 
|
| 68916 | 20  | 
private def stable_snapshot(  | 
21  | 
state: Document.State, version: Document.Version, name: Document.Node.Name): Document.Snapshot =  | 
|
22  | 
  {
 | 
|
23  | 
val snapshot = state.snapshot(name)  | 
|
24  | 
assert(version.id == snapshot.version.id)  | 
|
25  | 
snapshot  | 
|
26  | 
}  | 
|
27  | 
||
| 69013 | 28  | 
class Use_Theories_Result private[Headless](  | 
| 67883 | 29  | 
val state: Document.State,  | 
| 67889 | 30  | 
val version: Document.Version,  | 
| 68925 | 31  | 
val nodes: List[(Document.Node.Name, Document_Status.Node_Status)],  | 
32  | 
val nodes_committed: List[(Document.Node.Name, Document_Status.Node_Status)])  | 
|
| 67879 | 33  | 
  {
 | 
| 
69032
 
90bb4cabe1e8
clarified errors: no result from forced session.stop, check pending theories;
 
wenzelm 
parents: 
69013 
diff
changeset
 | 
34  | 
def nodes_pending: List[(Document.Node.Name, Document_Status.Node_Status)] =  | 
| 
 
90bb4cabe1e8
clarified errors: no result from forced session.stop, check pending theories;
 
wenzelm 
parents: 
69013 
diff
changeset
 | 
35  | 
    {
 | 
| 
 
90bb4cabe1e8
clarified errors: no result from forced session.stop, check pending theories;
 
wenzelm 
parents: 
69013 
diff
changeset
 | 
36  | 
val committed = nodes_committed.iterator.map(_._1).toSet  | 
| 
 
90bb4cabe1e8
clarified errors: no result from forced session.stop, check pending theories;
 
wenzelm 
parents: 
69013 
diff
changeset
 | 
37  | 
nodes.filter(p => !committed(p._1))  | 
| 
 
90bb4cabe1e8
clarified errors: no result from forced session.stop, check pending theories;
 
wenzelm 
parents: 
69013 
diff
changeset
 | 
38  | 
}  | 
| 
 
90bb4cabe1e8
clarified errors: no result from forced session.stop, check pending theories;
 
wenzelm 
parents: 
69013 
diff
changeset
 | 
39  | 
|
| 68925 | 40  | 
def snapshot(name: Document.Node.Name): Document.Snapshot =  | 
41  | 
stable_snapshot(state, version, name)  | 
|
42  | 
||
43  | 
def ok: Boolean =  | 
|
44  | 
      (nodes.iterator ++ nodes_committed.iterator).forall({ case (_, st) => st.ok })
 | 
|
| 67879 | 45  | 
}  | 
46  | 
||
| 69520 | 47  | 
class Session private[Headless](  | 
48  | 
session_name: String,  | 
|
49  | 
_session_options: => Options,  | 
|
50  | 
override val resources: Resources) extends isabelle.Session(_session_options, resources)  | 
|
51  | 
  {
 | 
|
52  | 
session =>  | 
|
| 
68694
 
03e104be99af
added check_delay / check_limit for more robust treatment of structurally broken theory sources (or genuine non-termination);
 
wenzelm 
parents: 
68365 
diff
changeset
 | 
53  | 
|
| 
 
03e104be99af
added check_delay / check_limit for more robust treatment of structurally broken theory sources (or genuine non-termination);
 
wenzelm 
parents: 
68365 
diff
changeset
 | 
54  | 
|
| 69520 | 55  | 
/* options */  | 
56  | 
||
57  | 
    def default_check_delay: Time = session_options.seconds("headless_check_delay")
 | 
|
58  | 
    def default_check_limit: Int = session_options.int("headless_check_limit")
 | 
|
59  | 
    def default_nodes_status_delay: Time = session_options.seconds("headless_nodes_status_delay")
 | 
|
60  | 
    def default_watchdog_timeout: Time = session_options.seconds("headless_watchdog_timeout")
 | 
|
61  | 
    def default_commit_cleanup_delay: Time = session_options.seconds("headless_commit_cleanup_delay")
 | 
|
| 67063 | 62  | 
|
| 68922 | 63  | 
|
64  | 
/* temporary directory */  | 
|
65  | 
||
| 67925 | 66  | 
    val tmp_dir: JFile = Isabelle_System.tmp_dir("server_session")
 | 
| 67946 | 67  | 
val tmp_dir_name: String = File.path(tmp_dir).implode  | 
| 67925 | 68  | 
|
| 68923 | 69  | 
def master_directory(master_dir: String): String =  | 
70  | 
proper_string(master_dir) getOrElse tmp_dir_name  | 
|
71  | 
||
| 67945 | 72  | 
override def toString: String = session_name  | 
73  | 
||
| 67925 | 74  | 
override def stop(): Process_Result =  | 
75  | 
    {
 | 
|
76  | 
      try { super.stop() }
 | 
|
77  | 
      finally { Isabelle_System.rm_tree(tmp_dir) }
 | 
|
78  | 
}  | 
|
79  | 
||
| 67936 | 80  | 
|
81  | 
/* theories */  | 
|
82  | 
||
| 68914 | 83  | 
private sealed case class Use_Theories_State(  | 
84  | 
last_update: Time = Time.now(),  | 
|
85  | 
nodes_status: Document_Status.Nodes_Status = Document_Status.Nodes_Status.empty,  | 
|
| 68925 | 86  | 
already_committed: Map[Document.Node.Name, Document_Status.Node_Status] = Map.empty,  | 
| 
70644
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
87  | 
result: Option[Exn.Result[Use_Theories_Result]] = None)  | 
| 68914 | 88  | 
    {
 | 
89  | 
def update(new_nodes_status: Document_Status.Nodes_Status): Use_Theories_State =  | 
|
90  | 
copy(last_update = Time.now(), nodes_status = new_nodes_status)  | 
|
91  | 
||
92  | 
def watchdog(watchdog_timeout: Time): Boolean =  | 
|
93  | 
watchdog_timeout > Time.zero && Time.now() - last_update > watchdog_timeout  | 
|
94  | 
||
| 
70644
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
95  | 
def finished_result: Boolean = result.isDefined  | 
| 
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
96  | 
|
| 
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
97  | 
def join_result: Option[(Exn.Result[Use_Theories_Result], Use_Theories_State)] =  | 
| 
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
98  | 
if (finished_result) Some((result.get, this)) else None  | 
| 
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
99  | 
|
| 
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
100  | 
def cancel_result: Use_Theories_State =  | 
| 
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
101  | 
if (finished_result) this else copy(result = Some(Exn.Exn(Exn.Interrupt())))  | 
| 
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
102  | 
|
| 68916 | 103  | 
def check_result(  | 
104  | 
state: Document.State,  | 
|
105  | 
version: Document.Version,  | 
|
| 68925 | 106  | 
dep_theories: List[Document.Node.Name],  | 
| 68916 | 107  | 
beyond_limit: Boolean,  | 
108  | 
watchdog_timeout: Time,  | 
|
109  | 
commit: Option[(Document.Snapshot, Document_Status.Node_Status) => Unit])  | 
|
110  | 
: Use_Theories_State =  | 
|
111  | 
      {
 | 
|
| 69035 | 112  | 
val already_committed1 =  | 
| 68916 | 113  | 
          if (commit.isDefined) {
 | 
| 69035 | 114  | 
            (already_committed /: dep_theories)({ case (committed, name) =>
 | 
115  | 
def parents_committed: Boolean =  | 
|
| 
70638
 
f164cec7ac22
clarified signature: prefer operations without position;
 
wenzelm 
parents: 
70637 
diff
changeset
 | 
116  | 
version.nodes(name).header.imports.forall(parent =>  | 
| 
 
f164cec7ac22
clarified signature: prefer operations without position;
 
wenzelm 
parents: 
70637 
diff
changeset
 | 
117  | 
resources.session_base.loaded_theory(parent) || committed.isDefinedAt(parent))  | 
| 69035 | 118  | 
if (!committed.isDefinedAt(name) && parents_committed &&  | 
119  | 
state.node_consolidated(version, name))  | 
|
120  | 
              {
 | 
|
121  | 
val snapshot = stable_snapshot(state, version, name)  | 
|
122  | 
val status = Document_Status.Node_Status.make(state, version, name)  | 
|
123  | 
commit.get.apply(snapshot, status)  | 
|
124  | 
committed + (name -> status)  | 
|
125  | 
}  | 
|
126  | 
else committed  | 
|
127  | 
})  | 
|
| 68916 | 128  | 
}  | 
| 69035 | 129  | 
else already_committed  | 
| 68916 | 130  | 
|
| 
70644
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
131  | 
val result1 =  | 
| 
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
132  | 
if (!finished_result &&  | 
| 
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
133  | 
(beyond_limit || watchdog(watchdog_timeout) ||  | 
| 
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
134  | 
dep_theories.forall(name =>  | 
| 
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
135  | 
already_committed1.isDefinedAt(name) ||  | 
| 
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
136  | 
state.node_consolidated(version, name) ||  | 
| 
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
137  | 
nodes_status.quasi_consolidated(name))))  | 
| 
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
138  | 
          {
 | 
| 
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
139  | 
val nodes =  | 
| 
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
140  | 
for (name <- dep_theories)  | 
| 
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
141  | 
              yield { (name -> Document_Status.Node_Status.make(state, version, name)) }
 | 
| 
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
142  | 
val nodes_committed =  | 
| 
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
143  | 
              for {
 | 
| 
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
144  | 
name <- dep_theories  | 
| 
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
145  | 
status <- already_committed1.get(name)  | 
| 
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
146  | 
} yield (name -> status)  | 
| 
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
147  | 
Some(Exn.Res(new Use_Theories_Result(state, version, nodes, nodes_committed)))  | 
| 
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
148  | 
}  | 
| 
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
149  | 
else result  | 
| 68925 | 150  | 
|
| 
70644
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
151  | 
copy(already_committed = already_committed1, result = result1)  | 
| 68916 | 152  | 
}  | 
| 68914 | 153  | 
}  | 
154  | 
||
| 
67064
 
fb487246ef4f
synchronous use_theories, based on consolidated_state;
 
wenzelm 
parents: 
67063 
diff
changeset
 | 
155  | 
def use_theories(  | 
| 
67940
 
b4e80f062fbf
clarified signature -- eliminated somewhat pointless positions;
 
wenzelm 
parents: 
67939 
diff
changeset
 | 
156  | 
theories: List[String],  | 
| 
67064
 
fb487246ef4f
synchronous use_theories, based on consolidated_state;
 
wenzelm 
parents: 
67063 
diff
changeset
 | 
157  | 
qualifier: String = Sessions.DRAFT,  | 
| 67881 | 158  | 
master_dir: String = "",  | 
| 69920 | 159  | 
unicode_symbols: Boolean = false,  | 
| 68943 | 160  | 
check_delay: Time = default_check_delay,  | 
| 69520 | 161  | 
check_limit: Int = default_check_limit,  | 
| 68947 | 162  | 
watchdog_timeout: Time = default_watchdog_timeout,  | 
| 68943 | 163  | 
nodes_status_delay: Time = default_nodes_status_delay,  | 
| 69458 | 164  | 
id: UUID.T = UUID.random(),  | 
| 
70625
 
1ae987cc052f
support for share_common_data after define_command and before actual update: this affects string particles of command tokens;
 
wenzelm 
parents: 
69920 
diff
changeset
 | 
165  | 
share_common_data: Boolean = false,  | 
| 68916 | 166  | 
// commit: must not block, must not fail  | 
167  | 
commit: Option[(Document.Snapshot, Document_Status.Node_Status) => Unit] = None,  | 
|
| 68981 | 168  | 
commit_cleanup_delay: Time = default_commit_cleanup_delay,  | 
| 69013 | 169  | 
progress: Progress = No_Progress): Use_Theories_Result =  | 
| 
67064
 
fb487246ef4f
synchronous use_theories, based on consolidated_state;
 
wenzelm 
parents: 
67063 
diff
changeset
 | 
170  | 
    {
 | 
| 
69562
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
171  | 
val dependencies =  | 
| 
68894
 
1dbdad1b57a5
more robust: load_theories after consumer is installed;
 
wenzelm 
parents: 
68888 
diff
changeset
 | 
172  | 
      {
 | 
| 
 
1dbdad1b57a5
more robust: load_theories after consumer is installed;
 
wenzelm 
parents: 
68888 
diff
changeset
 | 
173  | 
val import_names =  | 
| 68923 | 174  | 
theories.map(thy =>  | 
175  | 
resources.import_name(qualifier, master_directory(master_dir), thy) -> Position.none)  | 
|
| 
69562
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
176  | 
resources.dependencies(import_names, progress = progress).check_errors  | 
| 
68894
 
1dbdad1b57a5
more robust: load_theories after consumer is installed;
 
wenzelm 
parents: 
68888 
diff
changeset
 | 
177  | 
}  | 
| 
69562
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
178  | 
val dep_theories = dependencies.theories  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
179  | 
val dep_files =  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
180  | 
dependencies.loaded_files(false).flatMap(_._2).  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
181  | 
          map(path => Document.Node.Name(resources.append("", path)))
 | 
| 
67064
 
fb487246ef4f
synchronous use_theories, based on consolidated_state;
 
wenzelm 
parents: 
67063 
diff
changeset
 | 
182  | 
|
| 68914 | 183  | 
val use_theories_state = Synchronized(Use_Theories_State())  | 
| 
67064
 
fb487246ef4f
synchronous use_theories, based on consolidated_state;
 
wenzelm 
parents: 
67063 
diff
changeset
 | 
184  | 
|
| 69843 | 185  | 
def check_result_state(beyond_limit: Boolean = false)  | 
| 
67064
 
fb487246ef4f
synchronous use_theories, based on consolidated_state;
 
wenzelm 
parents: 
67063 
diff
changeset
 | 
186  | 
      {
 | 
| 
 
fb487246ef4f
synchronous use_theories, based on consolidated_state;
 
wenzelm 
parents: 
67063 
diff
changeset
 | 
187  | 
val state = session.current_state()  | 
| 
 
fb487246ef4f
synchronous use_theories, based on consolidated_state;
 
wenzelm 
parents: 
67063 
diff
changeset
 | 
188  | 
        state.stable_tip_version match {
 | 
| 
68694
 
03e104be99af
added check_delay / check_limit for more robust treatment of structurally broken theory sources (or genuine non-termination);
 
wenzelm 
parents: 
68365 
diff
changeset
 | 
189  | 
case Some(version) =>  | 
| 68916 | 190  | 
use_theories_state.change(  | 
191  | 
_.check_result(state, version, dep_theories, beyond_limit, watchdog_timeout, commit))  | 
|
| 
68694
 
03e104be99af
added check_delay / check_limit for more robust treatment of structurally broken theory sources (or genuine non-termination);
 
wenzelm 
parents: 
68365 
diff
changeset
 | 
192  | 
case None =>  | 
| 
67064
 
fb487246ef4f
synchronous use_theories, based on consolidated_state;
 
wenzelm 
parents: 
67063 
diff
changeset
 | 
193  | 
}  | 
| 
 
fb487246ef4f
synchronous use_theories, based on consolidated_state;
 
wenzelm 
parents: 
67063 
diff
changeset
 | 
194  | 
}  | 
| 
 
fb487246ef4f
synchronous use_theories, based on consolidated_state;
 
wenzelm 
parents: 
67063 
diff
changeset
 | 
195  | 
|
| 
67894
 
fee080c4045f
more robust check_state loop, even without session activity (e.g. idempotent use_theories);
 
wenzelm 
parents: 
67893 
diff
changeset
 | 
196  | 
val check_progress =  | 
| 
68694
 
03e104be99af
added check_delay / check_limit for more robust treatment of structurally broken theory sources (or genuine non-termination);
 
wenzelm 
parents: 
68365 
diff
changeset
 | 
197  | 
      {
 | 
| 
 
03e104be99af
added check_delay / check_limit for more robust treatment of structurally broken theory sources (or genuine non-termination);
 
wenzelm 
parents: 
68365 
diff
changeset
 | 
198  | 
var check_count = 0  | 
| 
 
03e104be99af
added check_delay / check_limit for more robust treatment of structurally broken theory sources (or genuine non-termination);
 
wenzelm 
parents: 
68365 
diff
changeset
 | 
199  | 
Event_Timer.request(Time.now(), repeat = Some(check_delay))  | 
| 
 
03e104be99af
added check_delay / check_limit for more robust treatment of structurally broken theory sources (or genuine non-termination);
 
wenzelm 
parents: 
68365 
diff
changeset
 | 
200  | 
          {
 | 
| 
70644
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
201  | 
if (progress.stopped) use_theories_state.change(_.cancel_result)  | 
| 
68694
 
03e104be99af
added check_delay / check_limit for more robust treatment of structurally broken theory sources (or genuine non-termination);
 
wenzelm 
parents: 
68365 
diff
changeset
 | 
202  | 
            else {
 | 
| 
 
03e104be99af
added check_delay / check_limit for more robust treatment of structurally broken theory sources (or genuine non-termination);
 
wenzelm 
parents: 
68365 
diff
changeset
 | 
203  | 
check_count += 1  | 
| 69843 | 204  | 
check_result_state(check_limit > 0 && check_count > check_limit)  | 
| 
68694
 
03e104be99af
added check_delay / check_limit for more robust treatment of structurally broken theory sources (or genuine non-termination);
 
wenzelm 
parents: 
68365 
diff
changeset
 | 
205  | 
}  | 
| 
 
03e104be99af
added check_delay / check_limit for more robust treatment of structurally broken theory sources (or genuine non-termination);
 
wenzelm 
parents: 
68365 
diff
changeset
 | 
206  | 
}  | 
| 
 
03e104be99af
added check_delay / check_limit for more robust treatment of structurally broken theory sources (or genuine non-termination);
 
wenzelm 
parents: 
68365 
diff
changeset
 | 
207  | 
}  | 
| 
67894
 
fee080c4045f
more robust check_state loop, even without session activity (e.g. idempotent use_theories);
 
wenzelm 
parents: 
67893 
diff
changeset
 | 
208  | 
|
| 68906 | 209  | 
val consumer =  | 
210  | 
      {
 | 
|
211  | 
val delay_nodes_status =  | 
|
212  | 
          Standard_Thread.delay_first(nodes_status_delay max Time.zero) {
 | 
|
| 
69818
 
60d0ee8f2ddb
more robust: avoid potentially unrelated snapshot for the sake of is_suppressed;
 
wenzelm 
parents: 
69817 
diff
changeset
 | 
213  | 
progress.nodes_status(use_theories_state.value.nodes_status)  | 
| 68906 | 214  | 
}  | 
| 
68770
 
add44e2b8cb0
optional notification of nodes_status (via progress);
 
wenzelm 
parents: 
68758 
diff
changeset
 | 
215  | 
|
| 
68936
 
90c08c7bab9c
continuously clean frontier of already committed theories: much less resource requirements;
 
wenzelm 
parents: 
68935 
diff
changeset
 | 
216  | 
val delay_commit_clean =  | 
| 68981 | 217  | 
          Standard_Thread.delay_first(commit_cleanup_delay max Time.zero) {
 | 
| 
68936
 
90c08c7bab9c
continuously clean frontier of already committed theories: much less resource requirements;
 
wenzelm 
parents: 
68935 
diff
changeset
 | 
218  | 
val clean = use_theories_state.value.already_committed.keySet  | 
| 
 
90c08c7bab9c
continuously clean frontier of already committed theories: much less resource requirements;
 
wenzelm 
parents: 
68935 
diff
changeset
 | 
219  | 
resources.clean_theories(session, id, clean)  | 
| 
 
90c08c7bab9c
continuously clean frontier of already committed theories: much less resource requirements;
 
wenzelm 
parents: 
68935 
diff
changeset
 | 
220  | 
}  | 
| 
 
90c08c7bab9c
continuously clean frontier of already committed theories: much less resource requirements;
 
wenzelm 
parents: 
68935 
diff
changeset
 | 
221  | 
|
| 68952 | 222  | 
val dep_theories_set = dep_theories.toSet  | 
223  | 
||
| 
67064
 
fb487246ef4f
synchronous use_theories, based on consolidated_state;
 
wenzelm 
parents: 
67063 
diff
changeset
 | 
224  | 
        Session.Consumer[Session.Commands_Changed](getClass.getName) {
 | 
| 68330 | 225  | 
case changed =>  | 
| 
68770
 
add44e2b8cb0
optional notification of nodes_status (via progress);
 
wenzelm 
parents: 
68758 
diff
changeset
 | 
226  | 
            if (changed.nodes.exists(dep_theories_set)) {
 | 
| 
 
add44e2b8cb0
optional notification of nodes_status (via progress);
 
wenzelm 
parents: 
68758 
diff
changeset
 | 
227  | 
val snapshot = session.snapshot()  | 
| 
 
add44e2b8cb0
optional notification of nodes_status (via progress);
 
wenzelm 
parents: 
68758 
diff
changeset
 | 
228  | 
val state = snapshot.state  | 
| 
 
add44e2b8cb0
optional notification of nodes_status (via progress);
 
wenzelm 
parents: 
68758 
diff
changeset
 | 
229  | 
val version = snapshot.version  | 
| 
 
add44e2b8cb0
optional notification of nodes_status (via progress);
 
wenzelm 
parents: 
68758 
diff
changeset
 | 
230  | 
|
| 68957 | 231  | 
val theory_progress =  | 
| 68914 | 232  | 
use_theories_state.change_result(st =>  | 
| 68903 | 233  | 
                  {
 | 
| 
68883
 
3653b3ad729e
clarified Thy_Resources.Session.use_theories: "terminated" node status is sufficient;
 
wenzelm 
parents: 
68771 
diff
changeset
 | 
234  | 
val domain =  | 
| 68914 | 235  | 
if (st.nodes_status.is_empty) dep_theories_set  | 
| 
68883
 
3653b3ad729e
clarified Thy_Resources.Session.use_theories: "terminated" node status is sufficient;
 
wenzelm 
parents: 
68771 
diff
changeset
 | 
236  | 
else changed.nodes.iterator.filter(dep_theories_set).toSet  | 
| 68899 | 237  | 
|
| 68903 | 238  | 
val (nodes_status_changed, nodes_status1) =  | 
| 
69255
 
800b1ce96fce
more general support for Isabelle/PIDE file formats -- less hardwired Bibtex operations;
 
wenzelm 
parents: 
69035 
diff
changeset
 | 
239  | 
st.nodes_status.update(resources, state, version,  | 
| 68903 | 240  | 
domain = Some(domain), trim = changed.assignment)  | 
| 68899 | 241  | 
|
| 68903 | 242  | 
                    if (nodes_status_delay >= Time.zero && nodes_status_changed) {
 | 
| 
68883
 
3653b3ad729e
clarified Thy_Resources.Session.use_theories: "terminated" node status is sufficient;
 
wenzelm 
parents: 
68771 
diff
changeset
 | 
243  | 
delay_nodes_status.invoke  | 
| 68899 | 244  | 
}  | 
| 
68883
 
3653b3ad729e
clarified Thy_Resources.Session.use_theories: "terminated" node status is sufficient;
 
wenzelm 
parents: 
68771 
diff
changeset
 | 
245  | 
|
| 68957 | 246  | 
val theory_progress =  | 
| 68905 | 247  | 
                      (for {
 | 
| 
69818
 
60d0ee8f2ddb
more robust: avoid potentially unrelated snapshot for the sake of is_suppressed;
 
wenzelm 
parents: 
69817 
diff
changeset
 | 
248  | 
(name, node_status) <- nodes_status1.present.iterator  | 
| 68959 | 249  | 
if changed.nodes.contains(name) && !st.already_committed.isDefinedAt(name)  | 
| 68962 | 250  | 
p1 = node_status.percentage  | 
251  | 
if p1 > 0 && Some(p1) != st.nodes_status.get(name).map(_.percentage)  | 
|
252  | 
} yield Progress.Theory(name.theory, percentage = Some(p1))).toList  | 
|
| 68903 | 253  | 
|
| 68957 | 254  | 
(theory_progress, st.update(nodes_status1))  | 
| 68903 | 255  | 
})  | 
| 68330 | 256  | 
|
| 68957 | 257  | 
theory_progress.foreach(progress.theory(_))  | 
| 68903 | 258  | 
|
| 69843 | 259  | 
check_result_state()  | 
| 
68936
 
90c08c7bab9c
continuously clean frontier of already committed theories: much less resource requirements;
 
wenzelm 
parents: 
68935 
diff
changeset
 | 
260  | 
|
| 68981 | 261  | 
              if (commit.isDefined && commit_cleanup_delay > Time.zero) {
 | 
| 
68936
 
90c08c7bab9c
continuously clean frontier of already committed theories: much less resource requirements;
 
wenzelm 
parents: 
68935 
diff
changeset
 | 
262  | 
if (use_theories_state.value.finished_result)  | 
| 
 
90c08c7bab9c
continuously clean frontier of already committed theories: much less resource requirements;
 
wenzelm 
parents: 
68935 
diff
changeset
 | 
263  | 
delay_commit_clean.revoke  | 
| 
 
90c08c7bab9c
continuously clean frontier of already committed theories: much less resource requirements;
 
wenzelm 
parents: 
68935 
diff
changeset
 | 
264  | 
else delay_commit_clean.invoke  | 
| 
 
90c08c7bab9c
continuously clean frontier of already committed theories: much less resource requirements;
 
wenzelm 
parents: 
68935 
diff
changeset
 | 
265  | 
}  | 
| 68330 | 266  | 
}  | 
| 
67064
 
fb487246ef4f
synchronous use_theories, based on consolidated_state;
 
wenzelm 
parents: 
67063 
diff
changeset
 | 
267  | 
}  | 
| 68906 | 268  | 
}  | 
| 
67064
 
fb487246ef4f
synchronous use_theories, based on consolidated_state;
 
wenzelm 
parents: 
67063 
diff
changeset
 | 
269  | 
|
| 67892 | 270  | 
      try {
 | 
271  | 
session.commands_changed += consumer  | 
|
| 
70625
 
1ae987cc052f
support for share_common_data after define_command and before actual update: this affects string particles of command tokens;
 
wenzelm 
parents: 
69920 
diff
changeset
 | 
272  | 
resources.load_theories(  | 
| 
 
1ae987cc052f
support for share_common_data after define_command and before actual update: this affects string particles of command tokens;
 
wenzelm 
parents: 
69920 
diff
changeset
 | 
273  | 
session, id, dep_theories, dep_files, unicode_symbols, share_common_data, progress)  | 
| 
70644
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
274  | 
use_theories_state.guarded_access(_.join_result)  | 
| 
67894
 
fee080c4045f
more robust check_state loop, even without session activity (e.g. idempotent use_theories);
 
wenzelm 
parents: 
67893 
diff
changeset
 | 
275  | 
check_progress.cancel  | 
| 67892 | 276  | 
}  | 
277  | 
      finally {
 | 
|
| 68907 | 278  | 
session.commands_changed -= consumer  | 
| 67892 | 279  | 
resources.unload_theories(session, id, dep_theories)  | 
280  | 
}  | 
|
| 
67884
 
43af581d7d8e
unload_theories after consolidation -- reset node_required;
 
wenzelm 
parents: 
67883 
diff
changeset
 | 
281  | 
|
| 
70644
 
b23a6dfcfd57
clarified state variable: avoid extra mutability via Promise;
 
wenzelm 
parents: 
70640 
diff
changeset
 | 
282  | 
Exn.release(use_theories_state.guarded_access(_.join_result))  | 
| 
67064
 
fb487246ef4f
synchronous use_theories, based on consolidated_state;
 
wenzelm 
parents: 
67063 
diff
changeset
 | 
283  | 
}  | 
| 67936 | 284  | 
|
| 67939 | 285  | 
def purge_theories(  | 
| 68915 | 286  | 
theories: List[String],  | 
287  | 
qualifier: String = Sessions.DRAFT,  | 
|
288  | 
master_dir: String = "",  | 
|
289  | 
all: Boolean = false): (List[Document.Node.Name], List[Document.Node.Name]) =  | 
|
290  | 
    {
 | 
|
| 68923 | 291  | 
val nodes =  | 
292  | 
if (all) None  | 
|
293  | 
else Some(theories.map(resources.import_name(qualifier, master_directory(master_dir), _)))  | 
|
| 68915 | 294  | 
resources.purge_theories(session, nodes)  | 
295  | 
}  | 
|
| 67063 | 296  | 
}  | 
297  | 
||
| 
67061
 
2efa25302f34
synchronous session start (similar to isabelle.vscode.Server);
 
wenzelm 
parents: 
67059 
diff
changeset
 | 
298  | 
|
| 67054 | 299  | 
|
| 69012 | 300  | 
/** resources **/  | 
| 68922 | 301  | 
|
| 69012 | 302  | 
object Resources  | 
303  | 
  {
 | 
|
| 69536 | 304  | 
def apply(base_info: Sessions.Base_Info, log: Logger = No_Logger): Resources =  | 
305  | 
new Resources(base_info, log = log)  | 
|
306  | 
||
307  | 
def make(  | 
|
308  | 
options: Options,  | 
|
309  | 
session_name: String,  | 
|
310  | 
session_dirs: List[Path] = Nil,  | 
|
311  | 
include_sessions: List[String] = Nil,  | 
|
312  | 
progress: Progress = No_Progress,  | 
|
313  | 
log: Logger = No_Logger): Resources =  | 
|
314  | 
    {
 | 
|
315  | 
val base_info =  | 
|
316  | 
Sessions.base_info(options, session_name, dirs = session_dirs,  | 
|
317  | 
include_sessions = include_sessions, progress = progress)  | 
|
318  | 
apply(base_info, log = log)  | 
|
319  | 
}  | 
|
320  | 
||
| 69012 | 321  | 
final class Theory private[Headless](  | 
322  | 
val node_name: Document.Node.Name,  | 
|
323  | 
val node_header: Document.Node.Header,  | 
|
324  | 
val text: String,  | 
|
325  | 
val node_required: Boolean)  | 
|
| 68922 | 326  | 
    {
 | 
| 69012 | 327  | 
override def toString: String = node_name.toString  | 
| 68922 | 328  | 
|
| 69012 | 329  | 
def node_perspective: Document.Node.Perspective_Text =  | 
330  | 
Document.Node.Perspective(node_required, Text.Perspective.empty, Document.Node.Overlays.empty)  | 
|
| 68922 | 331  | 
|
| 69012 | 332  | 
def make_edits(text_edits: List[Text.Edit]): List[Document.Edit_Text] =  | 
333  | 
List(node_name -> Document.Node.Deps(node_header),  | 
|
334  | 
node_name -> Document.Node.Edits(text_edits),  | 
|
335  | 
node_name -> node_perspective)  | 
|
| 68922 | 336  | 
|
| 69012 | 337  | 
def node_edits(old: Option[Theory]): List[Document.Edit_Text] =  | 
338  | 
      {
 | 
|
339  | 
val (text_edits, old_required) =  | 
|
340  | 
if (old.isEmpty) (Text.Edit.inserts(0, text), false)  | 
|
341  | 
else (Text.Edit.replace(0, old.get.text, text), old.get.node_required)  | 
|
| 
67887
 
a4d5342898b1
unload_theories: actually observe required state;
 
wenzelm 
parents: 
67885 
diff
changeset
 | 
342  | 
|
| 69012 | 343  | 
if (text_edits.isEmpty && node_required == old_required) Nil  | 
344  | 
else make_edits(text_edits)  | 
|
345  | 
}  | 
|
| 
67887
 
a4d5342898b1
unload_theories: actually observe required state;
 
wenzelm 
parents: 
67885 
diff
changeset
 | 
346  | 
|
| 69012 | 347  | 
def purge_edits: List[Document.Edit_Text] =  | 
348  | 
make_edits(Text.Edit.removes(0, text))  | 
|
| 67936 | 349  | 
|
| 69012 | 350  | 
def required(required: Boolean): Theory =  | 
351  | 
if (required == node_required) this  | 
|
352  | 
else new Theory(node_name, node_header, text, required)  | 
|
| 67936 | 353  | 
}  | 
354  | 
||
| 69012 | 355  | 
sealed case class State(  | 
| 
69562
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
356  | 
blobs: Map[Document.Node.Name, Document.Blob] = Map.empty,  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
357  | 
theories: Map[Document.Node.Name, Theory] = Map.empty,  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
358  | 
required: Multi_Map[Document.Node.Name, UUID.T] = Multi_Map.empty)  | 
| 
68936
 
90c08c7bab9c
continuously clean frontier of already committed theories: much less resource requirements;
 
wenzelm 
parents: 
68935 
diff
changeset
 | 
359  | 
    {
 | 
| 
69562
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
360  | 
/* blobs */  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
361  | 
|
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
362  | 
def doc_blobs: Document.Blobs = Document.Blobs(blobs)  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
363  | 
|
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
364  | 
def update_blobs(names: List[Document.Node.Name]): (Document.Blobs, State) =  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
365  | 
      {
 | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
366  | 
val new_blobs =  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
367  | 
names.flatMap(name =>  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
368  | 
          {
 | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
369  | 
val bytes = Bytes.read(name.path)  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
370  | 
def new_blob: Document.Blob =  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
371  | 
            {
 | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
372  | 
val text = bytes.text  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
373  | 
Document.Blob(bytes, text, Symbol.Text_Chunk(text), changed = true)  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
374  | 
}  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
375  | 
            blobs.get(name) match {
 | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
376  | 
case Some(blob) => if (blob.bytes == bytes) None else Some(name -> new_blob)  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
377  | 
case None => Some(name -> new_blob)  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
378  | 
}  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
379  | 
})  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
380  | 
val blobs1 = (blobs /: new_blobs)(_ + _)  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
381  | 
        val blobs2 = (blobs /: new_blobs)({ case (map, (a, b)) => map + (a -> b.unchanged) })
 | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
382  | 
(Document.Blobs(blobs1), copy(blobs = blobs2))  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
383  | 
}  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
384  | 
|
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
385  | 
def blob_edits(name: Document.Node.Name, old_blob: Option[Document.Blob])  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
386  | 
: List[Document.Edit_Text] =  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
387  | 
      {
 | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
388  | 
        val blob = blobs.getOrElse(name, error("Missing blob " + quote(name.toString)))
 | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
389  | 
val text_edits =  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
390  | 
          old_blob match {
 | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
391  | 
case None => List(Text.Edit.insert(0, blob.source))  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
392  | 
case Some(blob0) => Text.Edit.replace(0, blob0.source, blob.source)  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
393  | 
}  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
394  | 
if (text_edits.isEmpty) Nil  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
395  | 
else List(name -> Document.Node.Blob(blob), name -> Document.Node.Edits(text_edits))  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
396  | 
}  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
397  | 
|
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
398  | 
|
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
399  | 
/* theories */  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
400  | 
|
| 69012 | 401  | 
lazy val theory_graph: Graph[Document.Node.Name, Unit] =  | 
| 
68936
 
90c08c7bab9c
continuously clean frontier of already committed theories: much less resource requirements;
 
wenzelm 
parents: 
68935 
diff
changeset
 | 
402  | 
      {
 | 
| 69012 | 403  | 
val entries =  | 
404  | 
for ((name, theory) <- theories.toList)  | 
|
| 
70638
 
f164cec7ac22
clarified signature: prefer operations without position;
 
wenzelm 
parents: 
70637 
diff
changeset
 | 
405  | 
yield ((name, ()), theory.node_header.imports.filter(theories.isDefinedAt(_)))  | 
| 
70637
 
4c98d37e1448
prefer Theory_Ordering theory names are unique (due to proper session context);
 
wenzelm 
parents: 
70636 
diff
changeset
 | 
406  | 
Graph.make(entries, symmetric = true)(Document.Node.Name.Theory_Ordering)  | 
| 67888 | 407  | 
}  | 
| 67056 | 408  | 
|
| 69012 | 409  | 
def is_required(name: Document.Node.Name): Boolean = required.isDefinedAt(name)  | 
410  | 
||
| 69458 | 411  | 
def insert_required(id: UUID.T, names: List[Document.Node.Name]): State =  | 
| 69012 | 412  | 
copy(required = (required /: names)(_.insert(_, id)))  | 
413  | 
||
| 69458 | 414  | 
def remove_required(id: UUID.T, names: List[Document.Node.Name]): State =  | 
| 69012 | 415  | 
copy(required = (required /: names)(_.remove(_, id)))  | 
| 68958 | 416  | 
|
| 69012 | 417  | 
def update_theories(update: List[(Document.Node.Name, Theory)]): State =  | 
418  | 
copy(theories =  | 
|
419  | 
          (theories /: update)({ case (thys, (name, thy)) =>
 | 
|
420  | 
            thys.get(name) match {
 | 
|
421  | 
case Some(thy1) if thy1 == thy => thys  | 
|
422  | 
case _ => thys + (name -> thy)  | 
|
423  | 
}  | 
|
424  | 
}))  | 
|
425  | 
||
426  | 
def remove_theories(remove: List[Document.Node.Name]): State =  | 
|
| 67893 | 427  | 
      {
 | 
| 69012 | 428  | 
require(remove.forall(name => !is_required(name)))  | 
429  | 
copy(theories = theories -- remove)  | 
|
430  | 
}  | 
|
431  | 
||
| 69458 | 432  | 
def unload_theories(session: Session, id: UUID.T, dep_theories: List[Document.Node.Name])  | 
433  | 
: State =  | 
|
| 69012 | 434  | 
      {
 | 
435  | 
val st1 = remove_required(id, dep_theories)  | 
|
| 67893 | 436  | 
val theory_edits =  | 
| 69012 | 437  | 
          for {
 | 
438  | 
node_name <- dep_theories  | 
|
439  | 
theory <- st1.theories.get(node_name)  | 
|
440  | 
}  | 
|
| 67893 | 441  | 
          yield {
 | 
442  | 
val theory1 = theory.required(st1.is_required(node_name))  | 
|
| 69012 | 443  | 
val edits = theory1.node_edits(Some(theory))  | 
| 67893 | 444  | 
(edits, (node_name, theory1))  | 
445  | 
}  | 
|
| 
69562
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
446  | 
session.update(doc_blobs, theory_edits.flatMap(_._1))  | 
| 67893 | 447  | 
st1.update_theories(theory_edits.map(_._2))  | 
| 69012 | 448  | 
}  | 
449  | 
||
450  | 
def purge_theories(session: Session, nodes: List[Document.Node.Name])  | 
|
451  | 
: ((List[Document.Node.Name], List[Document.Node.Name]), State) =  | 
|
452  | 
      {
 | 
|
453  | 
val all_nodes = theory_graph.topological_order  | 
|
454  | 
val purge = nodes.filterNot(is_required(_)).toSet  | 
|
455  | 
||
456  | 
val retain = theory_graph.all_preds(all_nodes.filterNot(purge)).toSet  | 
|
457  | 
val (retained, purged) = all_nodes.partition(retain)  | 
|
458  | 
||
459  | 
val purge_edits = purged.flatMap(name => theories(name).purge_edits)  | 
|
| 
69562
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
460  | 
session.update(doc_blobs, purge_edits)  | 
| 69012 | 461  | 
|
462  | 
((purged, retained), remove_theories(purged))  | 
|
463  | 
}  | 
|
| 
67884
 
43af581d7d8e
unload_theories after consolidation -- reset node_required;
 
wenzelm 
parents: 
67883 
diff
changeset
 | 
464  | 
|
| 69012 | 465  | 
def frontier_theories(clean: Set[Document.Node.Name]): Set[Document.Node.Name] =  | 
466  | 
      {
 | 
|
467  | 
@tailrec def frontier(base: List[Document.Node.Name], front: Set[Document.Node.Name])  | 
|
468  | 
: Set[Document.Node.Name] =  | 
|
469  | 
        {
 | 
|
470  | 
val add = base.filter(b => theory_graph.imm_succs(b).forall(front))  | 
|
471  | 
if (add.isEmpty) front  | 
|
472  | 
          else {
 | 
|
473  | 
val pre_add = add.map(theory_graph.imm_preds)  | 
|
474  | 
val base1 = (pre_add.head /: pre_add.tail)(_ ++ _).toList.filter(clean)  | 
|
475  | 
frontier(base1, front ++ add)  | 
|
476  | 
}  | 
|
477  | 
}  | 
|
478  | 
frontier(theory_graph.maximals.filter(clean), Set.empty)  | 
|
479  | 
}  | 
|
480  | 
}  | 
|
| 
68936
 
90c08c7bab9c
continuously clean frontier of already committed theories: much less resource requirements;
 
wenzelm 
parents: 
68935 
diff
changeset
 | 
481  | 
}  | 
| 
 
90c08c7bab9c
continuously clean frontier of already committed theories: much less resource requirements;
 
wenzelm 
parents: 
68935 
diff
changeset
 | 
482  | 
|
| 69536 | 483  | 
class Resources private[Headless](  | 
484  | 
val session_base_info: Sessions.Base_Info,  | 
|
485  | 
log: Logger = No_Logger)  | 
|
486  | 
extends isabelle.Resources(session_base_info.check_base, log = log)  | 
|
| 
67884
 
43af581d7d8e
unload_theories after consolidation -- reset node_required;
 
wenzelm 
parents: 
67883 
diff
changeset
 | 
487  | 
  {
 | 
| 69012 | 488  | 
resources =>  | 
489  | 
||
| 
69538
 
faf547d2834c
clarified signature, notably cascade of dump_options, deps, resources, session;
 
wenzelm 
parents: 
69536 
diff
changeset
 | 
490  | 
def options: Options = session_base_info.options  | 
| 
 
faf547d2834c
clarified signature, notably cascade of dump_options, deps, resources, session;
 
wenzelm 
parents: 
69536 
diff
changeset
 | 
491  | 
|
| 69536 | 492  | 
|
493  | 
/* session */  | 
|
494  | 
||
495  | 
def start_session(print_mode: List[String] = Nil, progress: Progress = No_Progress): Session =  | 
|
496  | 
    {
 | 
|
497  | 
val session = new Session(session_base_info.session, options, resources)  | 
|
498  | 
||
499  | 
val session_error = Future.promise[String]  | 
|
500  | 
var session_phase: Session.Consumer[Session.Phase] = null  | 
|
501  | 
session_phase =  | 
|
502  | 
        Session.Consumer(getClass.getName) {
 | 
|
503  | 
case Session.Ready =>  | 
|
504  | 
session.phase_changed -= session_phase  | 
|
505  | 
            session_error.fulfill("")
 | 
|
506  | 
case Session.Terminated(result) if !result.ok =>  | 
|
507  | 
session.phase_changed -= session_phase  | 
|
508  | 
            session_error.fulfill("Session start failed: return code " + result.rc)
 | 
|
509  | 
case _ =>  | 
|
510  | 
}  | 
|
511  | 
session.phase_changed += session_phase  | 
|
512  | 
||
513  | 
      progress.echo("Starting session " + session_base_info.session + " ...")
 | 
|
514  | 
Isabelle_Process.start(session, options,  | 
|
515  | 
logic = session_base_info.session, dirs = session_base_info.dirs, modes = print_mode)  | 
|
516  | 
||
517  | 
      session_error.join match {
 | 
|
518  | 
case "" => session  | 
|
519  | 
case msg => session.stop(); error(msg)  | 
|
520  | 
}  | 
|
521  | 
}  | 
|
522  | 
||
523  | 
||
524  | 
/* theories */  | 
|
525  | 
||
| 69012 | 526  | 
private val state = Synchronized(Resources.State())  | 
527  | 
||
528  | 
def load_theories(  | 
|
529  | 
session: Session,  | 
|
| 69458 | 530  | 
id: UUID.T,  | 
| 69012 | 531  | 
dep_theories: List[Document.Node.Name],  | 
| 
69562
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
532  | 
dep_files: List[Document.Node.Name],  | 
| 69920 | 533  | 
unicode_symbols: Boolean,  | 
| 
70625
 
1ae987cc052f
support for share_common_data after define_command and before actual update: this affects string particles of command tokens;
 
wenzelm 
parents: 
69920 
diff
changeset
 | 
534  | 
share_common_data: Boolean,  | 
| 69012 | 535  | 
progress: Progress)  | 
536  | 
    {
 | 
|
537  | 
val loaded_theories =  | 
|
538  | 
for (node_name <- dep_theories)  | 
|
539  | 
        yield {
 | 
|
540  | 
val path = node_name.path  | 
|
541  | 
          if (!node_name.is_theory) error("Not a theory file: " + path)
 | 
|
542  | 
||
543  | 
progress.expose_interrupt()  | 
|
| 69920 | 544  | 
val text0 = File.read(path)  | 
545  | 
val text = if (unicode_symbols) Symbol.decode(text0) else text0  | 
|
| 69012 | 546  | 
val node_header = resources.check_thy_reader(node_name, Scan.char_reader(text))  | 
547  | 
new Resources.Theory(node_name, node_header, text, true)  | 
|
| 
68936
 
90c08c7bab9c
continuously clean frontier of already committed theories: much less resource requirements;
 
wenzelm 
parents: 
68935 
diff
changeset
 | 
548  | 
}  | 
| 69012 | 549  | 
|
550  | 
val loaded = loaded_theories.length  | 
|
551  | 
      if (loaded > 1) progress.echo("Loading " + loaded + " theories ...")
 | 
|
552  | 
||
553  | 
state.change(st =>  | 
|
554  | 
        {
 | 
|
| 
69562
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
555  | 
val (doc_blobs1, st1) = st.insert_required(id, dep_theories).update_blobs(dep_files)  | 
| 69012 | 556  | 
val theory_edits =  | 
557  | 
for (theory <- loaded_theories)  | 
|
558  | 
            yield {
 | 
|
559  | 
val node_name = theory.node_name  | 
|
560  | 
val theory1 = theory.required(st1.is_required(node_name))  | 
|
561  | 
val edits = theory1.node_edits(st1.theories.get(node_name))  | 
|
562  | 
(edits, (node_name, theory1))  | 
|
563  | 
}  | 
|
| 
69562
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
564  | 
val file_edits =  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
565  | 
            for { node_name <- dep_files if doc_blobs1.changed(node_name) }
 | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
566  | 
yield st1.blob_edits(node_name, st.blobs.get(node_name))  | 
| 
 
636b3c03a61a
include loaded_files as doc_blobs (without purging);
 
wenzelm 
parents: 
69538 
diff
changeset
 | 
567  | 
|
| 
70625
 
1ae987cc052f
support for share_common_data after define_command and before actual update: this affects string particles of command tokens;
 
wenzelm 
parents: 
69920 
diff
changeset
 | 
568  | 
session.update(doc_blobs1, theory_edits.flatMap(_._1) ::: file_edits.flatten,  | 
| 
 
1ae987cc052f
support for share_common_data after define_command and before actual update: this affects string particles of command tokens;
 
wenzelm 
parents: 
69920 
diff
changeset
 | 
569  | 
share_common_data = share_common_data)  | 
| 69012 | 570  | 
st1.update_theories(theory_edits.map(_._2))  | 
571  | 
})  | 
|
572  | 
}  | 
|
| 67936 | 573  | 
|
| 69458 | 574  | 
def unload_theories(session: Session, id: UUID.T, dep_theories: List[Document.Node.Name])  | 
| 69012 | 575  | 
    {
 | 
576  | 
state.change(_.unload_theories(session, id, dep_theories))  | 
|
577  | 
}  | 
|
578  | 
||
| 69458 | 579  | 
def clean_theories(session: Session, id: UUID.T, clean: Set[Document.Node.Name])  | 
| 69012 | 580  | 
    {
 | 
581  | 
state.change(st =>  | 
|
582  | 
        {
 | 
|
583  | 
val frontier = st.frontier_theories(clean).toList  | 
|
584  | 
if (frontier.isEmpty) st  | 
|
585  | 
          else {
 | 
|
586  | 
val st1 = st.unload_theories(session, id, frontier)  | 
|
587  | 
val (_, st2) = st1.purge_theories(session, frontier)  | 
|
588  | 
st2  | 
|
589  | 
}  | 
|
590  | 
})  | 
|
591  | 
}  | 
|
592  | 
||
593  | 
def purge_theories(session: Session, nodes: Option[List[Document.Node.Name]])  | 
|
594  | 
: (List[Document.Node.Name], List[Document.Node.Name]) =  | 
|
595  | 
    {
 | 
|
596  | 
state.change_result(st => st.purge_theories(session, nodes getOrElse st.theory_graph.keys))  | 
|
597  | 
}  | 
|
| 67936 | 598  | 
}  | 
| 67054 | 599  | 
}  |