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