| author | wenzelm | 
| Fri, 26 Aug 2022 23:37:21 +0200 | |
| changeset 75994 | f0ea03be7ceb | 
| parent 75970 | b4a04fa01677 | 
| child 76098 | bcca0fbb8a34 | 
| permissions | -rw-r--r-- | 
| 
68092
 
888d35a19866
store exports in session database, with asynchronous / parallel compression;
 
wenzelm 
parents:  
diff
changeset
 | 
1  | 
/* Title: Pure/Thy/export.scala  | 
| 
 
888d35a19866
store exports in session database, with asynchronous / parallel compression;
 
wenzelm 
parents:  
diff
changeset
 | 
2  | 
Author: Makarius  | 
| 
 
888d35a19866
store exports in session database, with asynchronous / parallel compression;
 
wenzelm 
parents:  
diff
changeset
 | 
3  | 
|
| 68102 | 4  | 
Manage theory exports: compressed blobs.  | 
| 
68092
 
888d35a19866
store exports in session database, with asynchronous / parallel compression;
 
wenzelm 
parents:  
diff
changeset
 | 
5  | 
*/  | 
| 
 
888d35a19866
store exports in session database, with asynchronous / parallel compression;
 
wenzelm 
parents:  
diff
changeset
 | 
6  | 
|
| 
 
888d35a19866
store exports in session database, with asynchronous / parallel compression;
 
wenzelm 
parents:  
diff
changeset
 | 
7  | 
package isabelle  | 
| 
 
888d35a19866
store exports in session database, with asynchronous / parallel compression;
 
wenzelm 
parents:  
diff
changeset
 | 
8  | 
|
| 68116 | 9  | 
|
10  | 
import scala.annotation.tailrec  | 
|
11  | 
import scala.util.matching.Regex  | 
|
12  | 
||
13  | 
||
| 75393 | 14  | 
object Export {
 | 
| 72691 | 15  | 
/* artefact names */  | 
16  | 
||
| 72844 | 17  | 
val DOCUMENT_ID = "PIDE/document_id"  | 
18  | 
val FILES = "PIDE/files"  | 
|
| 72702 | 19  | 
val MARKUP = "PIDE/markup"  | 
20  | 
val MESSAGES = "PIDE/messages"  | 
|
| 72691 | 21  | 
val DOCUMENT_PREFIX = "document/"  | 
| 73785 | 22  | 
val DOCUMENT_LATEX = DOCUMENT_PREFIX + "latex"  | 
23  | 
val DOCUMENT_CITATIONS = DOCUMENT_PREFIX + "citations"  | 
|
| 72691 | 24  | 
val THEORY_PREFIX: String = "theory/"  | 
25  | 
val PROOFS_PREFIX: String = "proofs/"  | 
|
| 69634 | 26  | 
|
| 69756 | 27  | 
  def explode_name(s: String): List[String] = space_explode('/', s)
 | 
28  | 
  def implode_name(elems: Iterable[String]): String = elems.mkString("/")
 | 
|
| 69634 | 29  | 
|
30  | 
||
| 
68092
 
888d35a19866
store exports in session database, with asynchronous / parallel compression;
 
wenzelm 
parents:  
diff
changeset
 | 
31  | 
/* SQL data model */  | 
| 
 
888d35a19866
store exports in session database, with asynchronous / parallel compression;
 
wenzelm 
parents:  
diff
changeset
 | 
32  | 
|
| 75393 | 33  | 
  object Data {
 | 
| 
68092
 
888d35a19866
store exports in session database, with asynchronous / parallel compression;
 
wenzelm 
parents:  
diff
changeset
 | 
34  | 
    val session_name = SQL.Column.string("session_name").make_primary_key
 | 
| 
 
888d35a19866
store exports in session database, with asynchronous / parallel compression;
 
wenzelm 
parents:  
diff
changeset
 | 
35  | 
    val theory_name = SQL.Column.string("theory_name").make_primary_key
 | 
| 
 
888d35a19866
store exports in session database, with asynchronous / parallel compression;
 
wenzelm 
parents:  
diff
changeset
 | 
36  | 
    val name = SQL.Column.string("name").make_primary_key
 | 
| 69788 | 37  | 
    val executable = SQL.Column.bool("executable")
 | 
| 
68092
 
888d35a19866
store exports in session database, with asynchronous / parallel compression;
 
wenzelm 
parents:  
diff
changeset
 | 
38  | 
    val compressed = SQL.Column.bool("compressed")
 | 
| 
 
888d35a19866
store exports in session database, with asynchronous / parallel compression;
 
wenzelm 
parents:  
diff
changeset
 | 
39  | 
    val body = SQL.Column.bytes("body")
 | 
| 
 
888d35a19866
store exports in session database, with asynchronous / parallel compression;
 
wenzelm 
parents:  
diff
changeset
 | 
40  | 
|
| 
 
888d35a19866
store exports in session database, with asynchronous / parallel compression;
 
wenzelm 
parents:  
diff
changeset
 | 
41  | 
val table =  | 
| 69788 | 42  | 
      SQL.Table("isabelle_exports",
 | 
43  | 
List(session_name, theory_name, name, executable, compressed, body))  | 
|
| 
68092
 
888d35a19866
store exports in session database, with asynchronous / parallel compression;
 
wenzelm 
parents:  
diff
changeset
 | 
44  | 
|
| 68116 | 45  | 
def where_equal(session_name: String, theory_name: String = "", name: String = ""): SQL.Source =  | 
| 
68092
 
888d35a19866
store exports in session database, with asynchronous / parallel compression;
 
wenzelm 
parents:  
diff
changeset
 | 
46  | 
"WHERE " + Data.session_name.equal(session_name) +  | 
| 68116 | 47  | 
(if (theory_name == "") "" else " AND " + Data.theory_name.equal(theory_name)) +  | 
48  | 
(if (name == "") "" else " AND " + Data.name.equal(name))  | 
|
49  | 
}  | 
|
50  | 
||
| 75674 | 51  | 
def compound_name(a: String, b: String): String =  | 
52  | 
if (a.isEmpty) b else a + ":" + b  | 
|
53  | 
||
| 75672 | 54  | 
  sealed case class Entry_Name(session: String = "", theory: String = "", name: String = "") {
 | 
| 75674 | 55  | 
val compound_name: String = Export.compound_name(theory, name)  | 
56  | 
||
| 75680 | 57  | 
    def make_path(prune: Int = 0): Path = {
 | 
| 75675 | 58  | 
      val elems = theory :: space_explode('/', name)
 | 
59  | 
      if (elems.length < prune + 1) {
 | 
|
60  | 
        error("Cannot prune path by " + prune + " element(s): " + Path.make(elems))
 | 
|
61  | 
}  | 
|
| 75680 | 62  | 
else Path.make(elems.drop(prune))  | 
| 75675 | 63  | 
}  | 
64  | 
||
| 75671 | 65  | 
    def readable(db: SQL.Database): Boolean = {
 | 
66  | 
val select = Data.table.select(List(Data.name), Data.where_equal(session, theory, name))  | 
|
67  | 
db.using_statement(select)(stmt => stmt.execute_query().next())  | 
|
68  | 
}  | 
|
69  | 
||
70  | 
    def read(db: SQL.Database, cache: XML.Cache): Option[Entry] = {
 | 
|
71  | 
val select =  | 
|
72  | 
Data.table.select(List(Data.executable, Data.compressed, Data.body),  | 
|
73  | 
Data.where_equal(session, theory, name))  | 
|
74  | 
      db.using_statement(select) { stmt =>
 | 
|
75  | 
val res = stmt.execute_query()  | 
|
76  | 
        if (res.next()) {
 | 
|
77  | 
val executable = res.bool(Data.executable)  | 
|
78  | 
val compressed = res.bool(Data.compressed)  | 
|
79  | 
val bytes = res.bytes(Data.body)  | 
|
80  | 
val body = Future.value(compressed, bytes)  | 
|
81  | 
Some(Entry(this, executable, body, cache))  | 
|
82  | 
}  | 
|
83  | 
else None  | 
|
84  | 
}  | 
|
85  | 
}  | 
|
| 
68092
 
888d35a19866
store exports in session database, with asynchronous / parallel compression;
 
wenzelm 
parents:  
diff
changeset
 | 
86  | 
}  | 
| 
 
888d35a19866
store exports in session database, with asynchronous / parallel compression;
 
wenzelm 
parents:  
diff
changeset
 | 
87  | 
|
| 75393 | 88  | 
  def read_theory_names(db: SQL.Database, session_name: String): List[String] = {
 | 
| 68222 | 89  | 
val select =  | 
| 
75860
 
2b2c09f4e7b5
proper export theory_names: theory/parents are not necessarily present (amending 4d27b520622a);
 
wenzelm 
parents: 
75825 
diff
changeset
 | 
90  | 
Data.table.select(List(Data.theory_name), Data.where_equal(session_name), distinct = true) +  | 
| 
75767
 
87f9748b214a
clarified signature: persistent theory_names in lexical order;
 
wenzelm 
parents: 
75766 
diff
changeset
 | 
91  | 
" ORDER BY " + Data.theory_name  | 
| 68222 | 92  | 
db.using_statement(select)(stmt =>  | 
93  | 
stmt.execute_query().iterator(_.string(Data.theory_name)).toList)  | 
|
94  | 
}  | 
|
95  | 
||
| 75674 | 96  | 
  def read_entry_names(db: SQL.Database, session_name: String): List[Entry_Name] = {
 | 
| 
75658
 
5905c7f484b3
clarified signature: read_theory_exports is already ordered;
 
wenzelm 
parents: 
75394 
diff
changeset
 | 
97  | 
val select =  | 
| 
 
5905c7f484b3
clarified signature: read_theory_exports is already ordered;
 
wenzelm 
parents: 
75394 
diff
changeset
 | 
98  | 
Data.table.select(List(Data.theory_name, Data.name), Data.where_equal(session_name)) +  | 
| 
 
5905c7f484b3
clarified signature: read_theory_exports is already ordered;
 
wenzelm 
parents: 
75394 
diff
changeset
 | 
99  | 
" ORDER BY " + Data.theory_name + ", " + Data.name  | 
| 68116 | 100  | 
db.using_statement(select)(stmt =>  | 
101  | 
stmt.execute_query().iterator(res =>  | 
|
| 75674 | 102  | 
Entry_Name(session = session_name,  | 
103  | 
theory = res.string(Data.theory_name),  | 
|
104  | 
name = res.string(Data.name))).toList)  | 
|
| 68115 | 105  | 
}  | 
106  | 
||
| 68104 | 107  | 
def message(msg: String, theory_name: String, name: String): String =  | 
108  | 
msg + " " + quote(name) + " for theory " + quote(theory_name)  | 
|
109  | 
||
| 72854 | 110  | 
def empty_entry(theory_name: String, name: String): Entry =  | 
| 75672 | 111  | 
Entry(Entry_Name(theory = theory_name, name = name),  | 
112  | 
false, Future.value(false, Bytes.empty), XML.Cache.none)  | 
|
| 
72634
 
5cea0993ee4f
clarified access to single database server vs. collection of database files;
 
wenzelm 
parents: 
72375 
diff
changeset
 | 
113  | 
|
| 
68092
 
888d35a19866
store exports in session database, with asynchronous / parallel compression;
 
wenzelm 
parents:  
diff
changeset
 | 
114  | 
sealed case class Entry(  | 
| 75671 | 115  | 
entry_name: Entry_Name,  | 
| 69788 | 116  | 
executable: Boolean,  | 
| 
72847
 
9dda93a753b1
clarified signature: provide XZ.Cache where Export.Entry is created;
 
wenzelm 
parents: 
72844 
diff
changeset
 | 
117  | 
body: Future[(Boolean, Bytes)],  | 
| 75393 | 118  | 
cache: XML.Cache  | 
119  | 
  ) {
 | 
|
| 75671 | 120  | 
def session_name: String = entry_name.session  | 
121  | 
def theory_name: String = entry_name.theory  | 
|
122  | 
def name: String = entry_name.name  | 
|
| 69635 | 123  | 
override def toString: String = name  | 
| 69630 | 124  | 
|
| 75674 | 125  | 
def compound_name: String = entry_name.compound_name  | 
| 71141 | 126  | 
|
| 72691 | 127  | 
def name_has_prefix(s: String): Boolean = name.startsWith(s)  | 
| 69634 | 128  | 
val name_elems: List[String] = explode_name(name)  | 
129  | 
||
130  | 
def name_extends(elems: List[String]): Boolean =  | 
|
131  | 
name_elems.startsWith(elems) && name_elems != elems  | 
|
132  | 
||
| 
72847
 
9dda93a753b1
clarified signature: provide XZ.Cache where Export.Entry is created;
 
wenzelm 
parents: 
72844 
diff
changeset
 | 
133  | 
def text: String = uncompressed.text  | 
| 
68092
 
888d35a19866
store exports in session database, with asynchronous / parallel compression;
 
wenzelm 
parents:  
diff
changeset
 | 
134  | 
|
| 75393 | 135  | 
    def uncompressed: Bytes = {
 | 
| 69629 | 136  | 
val (compressed, bytes) = body.join  | 
| 
73031
 
f93f0597f4fb
clarified signature: absorb XZ.Cache into XML.Cache;
 
wenzelm 
parents: 
73024 
diff
changeset
 | 
137  | 
if (compressed) bytes.uncompress(cache = cache.xz) else bytes  | 
| 69629 | 138  | 
}  | 
139  | 
||
| 
72847
 
9dda93a753b1
clarified signature: provide XZ.Cache where Export.Entry is created;
 
wenzelm 
parents: 
72844 
diff
changeset
 | 
140  | 
def uncompressed_yxml: XML.Body =  | 
| 73033 | 141  | 
YXML.parse_body(UTF8.decode_permissive(uncompressed), cache = cache)  | 
| 69629 | 142  | 
|
| 75393 | 143  | 
    def write(db: SQL.Database): Unit = {
 | 
| 68167 | 144  | 
val (compressed, bytes) = body.join  | 
| 75394 | 145  | 
      db.using_statement(Data.table.insert()) { stmt =>
 | 
| 
68092
 
888d35a19866
store exports in session database, with asynchronous / parallel compression;
 
wenzelm 
parents:  
diff
changeset
 | 
146  | 
stmt.string(1) = session_name  | 
| 
 
888d35a19866
store exports in session database, with asynchronous / parallel compression;
 
wenzelm 
parents:  
diff
changeset
 | 
147  | 
stmt.string(2) = theory_name  | 
| 
 
888d35a19866
store exports in session database, with asynchronous / parallel compression;
 
wenzelm 
parents:  
diff
changeset
 | 
148  | 
stmt.string(3) = name  | 
| 69788 | 149  | 
stmt.bool(4) = executable  | 
150  | 
stmt.bool(5) = compressed  | 
|
151  | 
stmt.bytes(6) = bytes  | 
|
| 
68092
 
888d35a19866
store exports in session database, with asynchronous / parallel compression;
 
wenzelm 
parents:  
diff
changeset
 | 
152  | 
stmt.execute()  | 
| 75394 | 153  | 
}  | 
| 
68092
 
888d35a19866
store exports in session database, with asynchronous / parallel compression;
 
wenzelm 
parents:  
diff
changeset
 | 
154  | 
}  | 
| 68116 | 155  | 
}  | 
156  | 
||
| 75393 | 157  | 
  def make_regex(pattern: String): Regex = {
 | 
| 68116 | 158  | 
@tailrec def make(result: List[String], depth: Int, chs: List[Char]): Regex =  | 
159  | 
      chs match {
 | 
|
160  | 
        case '*' :: '*' :: rest => make("[^:]*" :: result, depth, rest)
 | 
|
161  | 
        case '*' :: rest => make("[^:/]*" :: result, depth, rest)
 | 
|
162  | 
        case '?' :: rest => make("[^:/]" :: result, depth, rest)
 | 
|
163  | 
        case '\\' :: c :: rest => make(("\\" + c) :: result, depth, rest)
 | 
|
164  | 
        case '{' :: rest => make("(" :: result, depth + 1, rest)
 | 
|
165  | 
        case ',' :: rest if depth > 0 => make("|" :: result, depth, rest)
 | 
|
166  | 
        case '}' :: rest if depth > 0 => make(")" :: result, depth - 1, rest)
 | 
|
167  | 
        case c :: rest if ".+()".contains(c) => make(("\\" + c) :: result, depth, rest)
 | 
|
168  | 
case c :: rest => make(c.toString :: result, depth, rest)  | 
|
169  | 
case Nil => result.reverse.mkString.r  | 
|
170  | 
}  | 
|
171  | 
make(Nil, 0, pattern.toList)  | 
|
| 
68092
 
888d35a19866
store exports in session database, with asynchronous / parallel compression;
 
wenzelm 
parents:  
diff
changeset
 | 
172  | 
}  | 
| 
 
888d35a19866
store exports in session database, with asynchronous / parallel compression;
 
wenzelm 
parents:  
diff
changeset
 | 
173  | 
|
| 75674 | 174  | 
  def make_matcher(pats: List[String]): Entry_Name => Boolean = {
 | 
| 
75658
 
5905c7f484b3
clarified signature: read_theory_exports is already ordered;
 
wenzelm 
parents: 
75394 
diff
changeset
 | 
175  | 
val regs = pats.map(make_regex)  | 
| 75674 | 176  | 
(entry_name: Entry_Name) =>  | 
177  | 
regs.exists(_.pattern.matcher(entry_name.compound_name).matches)  | 
|
| 68151 | 178  | 
}  | 
179  | 
||
| 
72847
 
9dda93a753b1
clarified signature: provide XZ.Cache where Export.Entry is created;
 
wenzelm 
parents: 
72844 
diff
changeset
 | 
180  | 
def make_entry(  | 
| 75393 | 181  | 
session_name: String,  | 
182  | 
args: Protocol.Export.Args,  | 
|
183  | 
bytes: Bytes,  | 
|
184  | 
cache: XML.Cache  | 
|
185  | 
  ): Entry = {
 | 
|
| 
72847
 
9dda93a753b1
clarified signature: provide XZ.Cache where Export.Entry is created;
 
wenzelm 
parents: 
72844 
diff
changeset
 | 
186  | 
val body =  | 
| 
73031
 
f93f0597f4fb
clarified signature: absorb XZ.Cache into XML.Cache;
 
wenzelm 
parents: 
73024 
diff
changeset
 | 
187  | 
if (args.compress) Future.fork(bytes.maybe_compress(cache = cache.xz))  | 
| 
72847
 
9dda93a753b1
clarified signature: provide XZ.Cache where Export.Entry is created;
 
wenzelm 
parents: 
72844 
diff
changeset
 | 
188  | 
else Future.value((false, bytes))  | 
| 75672 | 189  | 
val entry_name = Entry_Name(session = session_name, theory = args.theory_name, name = args.name)  | 
| 75671 | 190  | 
Entry(entry_name, args.executable, body, cache)  | 
| 68831 | 191  | 
}  | 
192  | 
||
| 
68092
 
888d35a19866
store exports in session database, with asynchronous / parallel compression;
 
wenzelm 
parents:  
diff
changeset
 | 
193  | 
|
| 
 
888d35a19866
store exports in session database, with asynchronous / parallel compression;
 
wenzelm 
parents:  
diff
changeset
 | 
194  | 
/* database consumer thread */  | 
| 
 
888d35a19866
store exports in session database, with asynchronous / parallel compression;
 
wenzelm 
parents:  
diff
changeset
 | 
195  | 
|
| 74255 | 196  | 
def consumer(db: SQL.Database, cache: XML.Cache, progress: Progress = new Progress): Consumer =  | 
197  | 
new Consumer(db, cache, progress)  | 
|
| 
68092
 
888d35a19866
store exports in session database, with asynchronous / parallel compression;
 
wenzelm 
parents:  
diff
changeset
 | 
198  | 
|
| 75393 | 199  | 
  class Consumer private[Export](db: SQL.Database, cache: XML.Cache, progress: Progress) {
 | 
| 68924 | 200  | 
private val errors = Synchronized[List[String]](Nil)  | 
| 
68092
 
888d35a19866
store exports in session database, with asynchronous / parallel compression;
 
wenzelm 
parents:  
diff
changeset
 | 
201  | 
|
| 
 
888d35a19866
store exports in session database, with asynchronous / parallel compression;
 
wenzelm 
parents:  
diff
changeset
 | 
202  | 
private val consumer =  | 
| 
71145
 
2f782d5f5d5a
improved performance of session exports via bulk transactions;
 
wenzelm 
parents: 
71141 
diff
changeset
 | 
203  | 
Consumer_Thread.fork_bulk[(Entry, Boolean)](name = "export")(  | 
| 
 
2f782d5f5d5a
improved performance of session exports via bulk transactions;
 
wenzelm 
parents: 
71141 
diff
changeset
 | 
204  | 
        bulk = { case (entry, _) => entry.body.is_finished },
 | 
| 
 
2f782d5f5d5a
improved performance of session exports via bulk transactions;
 
wenzelm 
parents: 
71141 
diff
changeset
 | 
205  | 
consume =  | 
| 75394 | 206  | 
          { (args: List[(Entry, Boolean)]) =>
 | 
| 
71145
 
2f782d5f5d5a
improved performance of session exports via bulk transactions;
 
wenzelm 
parents: 
71141 
diff
changeset
 | 
207  | 
val results =  | 
| 
 
2f782d5f5d5a
improved performance of session exports via bulk transactions;
 
wenzelm 
parents: 
71141 
diff
changeset
 | 
208  | 
              db.transaction {
 | 
| 74256 | 209  | 
for ((entry, strict) <- args)  | 
| 
71145
 
2f782d5f5d5a
improved performance of session exports via bulk transactions;
 
wenzelm 
parents: 
71141 
diff
changeset
 | 
210  | 
                yield {
 | 
| 74257 | 211  | 
                  if (progress.stopped) {
 | 
212  | 
entry.body.cancel()  | 
|
213  | 
Exn.Res(())  | 
|
214  | 
}  | 
|
| 75671 | 215  | 
                  else if (entry.entry_name.readable(db)) {
 | 
| 
71145
 
2f782d5f5d5a
improved performance of session exports via bulk transactions;
 
wenzelm 
parents: 
71141 
diff
changeset
 | 
216  | 
                    if (strict) {
 | 
| 
 
2f782d5f5d5a
improved performance of session exports via bulk transactions;
 
wenzelm 
parents: 
71141 
diff
changeset
 | 
217  | 
                      val msg = message("Duplicate export", entry.theory_name, entry.name)
 | 
| 
 
2f782d5f5d5a
improved performance of session exports via bulk transactions;
 
wenzelm 
parents: 
71141 
diff
changeset
 | 
218  | 
errors.change(msg :: _)  | 
| 
 
2f782d5f5d5a
improved performance of session exports via bulk transactions;
 
wenzelm 
parents: 
71141 
diff
changeset
 | 
219  | 
}  | 
| 
 
2f782d5f5d5a
improved performance of session exports via bulk transactions;
 
wenzelm 
parents: 
71141 
diff
changeset
 | 
220  | 
Exn.Res(())  | 
| 
 
2f782d5f5d5a
improved performance of session exports via bulk transactions;
 
wenzelm 
parents: 
71141 
diff
changeset
 | 
221  | 
}  | 
| 
 
2f782d5f5d5a
improved performance of session exports via bulk transactions;
 
wenzelm 
parents: 
71141 
diff
changeset
 | 
222  | 
                  else Exn.capture { entry.write(db) }
 | 
| 
 
2f782d5f5d5a
improved performance of session exports via bulk transactions;
 
wenzelm 
parents: 
71141 
diff
changeset
 | 
223  | 
}  | 
| 70499 | 224  | 
}  | 
| 
71145
 
2f782d5f5d5a
improved performance of session exports via bulk transactions;
 
wenzelm 
parents: 
71141 
diff
changeset
 | 
225  | 
(results, true)  | 
| 
 
2f782d5f5d5a
improved performance of session exports via bulk transactions;
 
wenzelm 
parents: 
71141 
diff
changeset
 | 
226  | 
})  | 
| 
68092
 
888d35a19866
store exports in session database, with asynchronous / parallel compression;
 
wenzelm 
parents:  
diff
changeset
 | 
227  | 
|
| 
75762
 
985c3a64748c
clarified signature: more uniform treatment of empty exports;
 
wenzelm 
parents: 
75759 
diff
changeset
 | 
228  | 
    def make_entry(session_name: String, args: Protocol.Export.Args, body: Bytes): Unit = {
 | 
| 
 
985c3a64748c
clarified signature: more uniform treatment of empty exports;
 
wenzelm 
parents: 
75759 
diff
changeset
 | 
229  | 
      if (!progress.stopped && !body.is_empty) {
 | 
| 
 
985c3a64748c
clarified signature: more uniform treatment of empty exports;
 
wenzelm 
parents: 
75759 
diff
changeset
 | 
230  | 
consumer.send(Export.make_entry(session_name, args, body, cache) -> args.strict)  | 
| 74257 | 231  | 
}  | 
232  | 
}  | 
|
| 
68092
 
888d35a19866
store exports in session database, with asynchronous / parallel compression;
 
wenzelm 
parents:  
diff
changeset
 | 
233  | 
|
| 75393 | 234  | 
    def shutdown(close: Boolean = false): List[String] = {
 | 
| 
68092
 
888d35a19866
store exports in session database, with asynchronous / parallel compression;
 
wenzelm 
parents:  
diff
changeset
 | 
235  | 
consumer.shutdown()  | 
| 
 
888d35a19866
store exports in session database, with asynchronous / parallel compression;
 
wenzelm 
parents:  
diff
changeset
 | 
236  | 
if (close) db.close()  | 
| 74255 | 237  | 
      errors.value.reverse ::: (if (progress.stopped) List("Export stopped") else Nil)
 | 
| 
68092
 
888d35a19866
store exports in session database, with asynchronous / parallel compression;
 
wenzelm 
parents:  
diff
changeset
 | 
238  | 
}  | 
| 
 
888d35a19866
store exports in session database, with asynchronous / parallel compression;
 
wenzelm 
parents:  
diff
changeset
 | 
239  | 
}  | 
| 68116 | 240  | 
|
241  | 
||
| 75786 | 242  | 
/* context for database access */  | 
| 75772 | 243  | 
|
| 75786 | 244  | 
  def open_database_context(store: Sessions.Store): Database_Context = {
 | 
245  | 
val database_server = if (store.database_server) Some(store.open_database_server()) else None  | 
|
246  | 
new Database_Context(store, database_server)  | 
|
247  | 
}  | 
|
248  | 
||
249  | 
def open_session_context0(store: Sessions.Store, session: String): Session_Context =  | 
|
250  | 
open_database_context(store).open_session0(session, close_database_context = true)  | 
|
| 75772 | 251  | 
|
| 75786 | 252  | 
def open_session_context(  | 
253  | 
store: Sessions.Store,  | 
|
254  | 
session_base_info: Sessions.Base_Info,  | 
|
255  | 
document_snapshot: Option[Document.Snapshot] = None  | 
|
256  | 
  ): Session_Context = {
 | 
|
257  | 
open_database_context(store).open_session(  | 
|
258  | 
session_base_info, document_snapshot = document_snapshot, close_database_context = true)  | 
|
259  | 
}  | 
|
| 75771 | 260  | 
|
| 75786 | 261  | 
class Database_Context private[Export](  | 
262  | 
val store: Sessions.Store,  | 
|
263  | 
val database_server: Option[SQL.Database]  | 
|
264  | 
  ) extends AutoCloseable {
 | 
|
265  | 
database_context =>  | 
|
| 
75782
 
dba571dd0ba9
clarified signature: prefer Export.Session_Context over Sessions.Database_Context;
 
wenzelm 
parents: 
75780 
diff
changeset
 | 
266  | 
|
| 75786 | 267  | 
    override def toString: String = {
 | 
268  | 
val s =  | 
|
269  | 
        database_server match {
 | 
|
270  | 
case Some(db) => db.toString  | 
|
271  | 
          case None => "input_dirs = " + store.input_dirs.map(_.absolute).mkString(", ")
 | 
|
272  | 
}  | 
|
273  | 
      "Database_Context(" + s + ")"
 | 
|
274  | 
}  | 
|
275  | 
||
276  | 
def cache: Term.Cache = store.cache  | 
|
| 
75759
 
0cdccd0d1699
clarified context for retrieval: more explicit types, with optional close() operation;
 
wenzelm 
parents: 
75757 
diff
changeset
 | 
277  | 
|
| 75786 | 278  | 
def close(): Unit = database_server.foreach(_.close())  | 
279  | 
||
| 75970 | 280  | 
def open_database(session: String, output: Boolean = false): Session_Database =  | 
| 75786 | 281  | 
      database_server match {
 | 
| 75787 | 282  | 
case Some(db) => new Session_Database(session, db)  | 
283  | 
case None =>  | 
|
| 75970 | 284  | 
          new Session_Database(session, store.open_database(session, output = output)) {
 | 
| 75787 | 285  | 
override def close(): Unit = db.close()  | 
286  | 
}  | 
|
| 75786 | 287  | 
}  | 
288  | 
||
289  | 
def open_session0(session: String, close_database_context: Boolean = false): Session_Context =  | 
|
290  | 
open_session(Sessions.base_info0(session), close_database_context = close_database_context)  | 
|
| 
75779
 
5470c67bd772
clarified signature: prefer Export.Session_Context;
 
wenzelm 
parents: 
75778 
diff
changeset
 | 
291  | 
|
| 
75759
 
0cdccd0d1699
clarified context for retrieval: more explicit types, with optional close() operation;
 
wenzelm 
parents: 
75757 
diff
changeset
 | 
292  | 
def open_session(  | 
| 
75773
 
11b2bf6f90d8
clarified signature: less redundant -- Sessions.Base_Info already specifies the main session;
 
wenzelm 
parents: 
75772 
diff
changeset
 | 
293  | 
session_base_info: Sessions.Base_Info,  | 
| 75772 | 294  | 
document_snapshot: Option[Document.Snapshot] = None,  | 
| 75786 | 295  | 
close_database_context: Boolean = false  | 
| 
75759
 
0cdccd0d1699
clarified context for retrieval: more explicit types, with optional close() operation;
 
wenzelm 
parents: 
75757 
diff
changeset
 | 
296  | 
    ): Session_Context = {
 | 
| 
75921
 
423021c98500
clarified signature: Sessions.Base_Info follows Sessions.Base;
 
wenzelm 
parents: 
75920 
diff
changeset
 | 
297  | 
val session_name = session_base_info.check_errors.session_name  | 
| 
75778
 
d18c96b9b955
prefer Export.Context/Session_Context/Theory_Context over Sessions.Database_Context;
 
wenzelm 
parents: 
75775 
diff
changeset
 | 
298  | 
val session_hierarchy = session_base_info.sessions_structure.build_hierarchy(session_name)  | 
| 
75773
 
11b2bf6f90d8
clarified signature: less redundant -- Sessions.Base_Info already specifies the main session;
 
wenzelm 
parents: 
75772 
diff
changeset
 | 
299  | 
val session_databases =  | 
| 75786 | 300  | 
        database_server match {
 | 
| 75771 | 301  | 
case Some(db) => session_hierarchy.map(name => new Session_Database(name, db))  | 
302  | 
case None =>  | 
|
| 
75775
 
70a65ee4a738
clarified signature: more robust treatment of server;
 
wenzelm 
parents: 
75774 
diff
changeset
 | 
303  | 
val attempts =  | 
| 
 
70a65ee4a738
clarified signature: more robust treatment of server;
 
wenzelm 
parents: 
75774 
diff
changeset
 | 
304  | 
session_hierarchy.map(name => name -> store.try_open_database(name, server = false))  | 
| 75771 | 305  | 
            attempts.collectFirst({ case (name, None) => name }) match {
 | 
306  | 
case Some(bad) =>  | 
|
307  | 
for ((_, Some(db)) <- attempts) db.close()  | 
|
| 75791 | 308  | 
store.error_database(bad)  | 
| 
75764
 
07e097f60b85
clarified signature: more robust close operation;
 
wenzelm 
parents: 
75762 
diff
changeset
 | 
309  | 
case None =>  | 
| 75771 | 310  | 
                for ((name, Some(db)) <- attempts) yield {
 | 
| 
75764
 
07e097f60b85
clarified signature: more robust close operation;
 
wenzelm 
parents: 
75762 
diff
changeset
 | 
311  | 
                  new Session_Database(name, db) { override def close(): Unit = this.db.close() }
 | 
| 
 
07e097f60b85
clarified signature: more robust close operation;
 
wenzelm 
parents: 
75762 
diff
changeset
 | 
312  | 
}  | 
| 
 
07e097f60b85
clarified signature: more robust close operation;
 
wenzelm 
parents: 
75762 
diff
changeset
 | 
313  | 
}  | 
| 75771 | 314  | 
}  | 
| 75786 | 315  | 
      new Session_Context(database_context, session_base_info, session_databases, document_snapshot) {
 | 
| 75772 | 316  | 
        override def close(): Unit = {
 | 
317  | 
session_databases.foreach(_.close())  | 
|
| 75786 | 318  | 
if (close_database_context) database_context.close()  | 
| 75772 | 319  | 
}  | 
| 
75759
 
0cdccd0d1699
clarified context for retrieval: more explicit types, with optional close() operation;
 
wenzelm 
parents: 
75757 
diff
changeset
 | 
320  | 
}  | 
| 
 
0cdccd0d1699
clarified context for retrieval: more explicit types, with optional close() operation;
 
wenzelm 
parents: 
75757 
diff
changeset
 | 
321  | 
}  | 
| 
 
0cdccd0d1699
clarified context for retrieval: more explicit types, with optional close() operation;
 
wenzelm 
parents: 
75757 
diff
changeset
 | 
322  | 
}  | 
| 
 
0cdccd0d1699
clarified context for retrieval: more explicit types, with optional close() operation;
 
wenzelm 
parents: 
75757 
diff
changeset
 | 
323  | 
|
| 75789 | 324  | 
class Session_Database private[Export](val session: String, val db: SQL.Database)  | 
325  | 
  extends AutoCloseable {
 | 
|
326  | 
def close(): Unit = ()  | 
|
327  | 
||
328  | 
lazy private [Export] val theory_names: List[String] = read_theory_names(db, session)  | 
|
329  | 
lazy private [Export] val entry_names: List[Entry_Name] = read_entry_names(db, session)  | 
|
330  | 
}  | 
|
331  | 
||
| 
75759
 
0cdccd0d1699
clarified context for retrieval: more explicit types, with optional close() operation;
 
wenzelm 
parents: 
75757 
diff
changeset
 | 
332  | 
class Session_Context private[Export](  | 
| 75786 | 333  | 
val database_context: Database_Context,  | 
| 
75778
 
d18c96b9b955
prefer Export.Context/Session_Context/Theory_Context over Sessions.Database_Context;
 
wenzelm 
parents: 
75775 
diff
changeset
 | 
334  | 
session_base_info: Sessions.Base_Info,  | 
| 
75770
 
62e2c6f65f9a
clarified Document.Snapshot.all_exports: refer to material from this (virtual) session;
 
wenzelm 
parents: 
75769 
diff
changeset
 | 
335  | 
db_hierarchy: List[Session_Database],  | 
| 
 
62e2c6f65f9a
clarified Document.Snapshot.all_exports: refer to material from this (virtual) session;
 
wenzelm 
parents: 
75769 
diff
changeset
 | 
336  | 
document_snapshot: Option[Document.Snapshot]  | 
| 
75759
 
0cdccd0d1699
clarified context for retrieval: more explicit types, with optional close() operation;
 
wenzelm 
parents: 
75757 
diff
changeset
 | 
337  | 
  ) extends AutoCloseable {
 | 
| 
 
0cdccd0d1699
clarified context for retrieval: more explicit types, with optional close() operation;
 
wenzelm 
parents: 
75757 
diff
changeset
 | 
338  | 
session_context =>  | 
| 
 
0cdccd0d1699
clarified context for retrieval: more explicit types, with optional close() operation;
 
wenzelm 
parents: 
75757 
diff
changeset
 | 
339  | 
|
| 
 
0cdccd0d1699
clarified context for retrieval: more explicit types, with optional close() operation;
 
wenzelm 
parents: 
75757 
diff
changeset
 | 
340  | 
def close(): Unit = ()  | 
| 
 
0cdccd0d1699
clarified context for retrieval: more explicit types, with optional close() operation;
 
wenzelm 
parents: 
75757 
diff
changeset
 | 
341  | 
|
| 75786 | 342  | 
def cache: Term.Cache = database_context.cache  | 
| 
75778
 
d18c96b9b955
prefer Export.Context/Session_Context/Theory_Context over Sessions.Database_Context;
 
wenzelm 
parents: 
75775 
diff
changeset
 | 
343  | 
|
| 
 
d18c96b9b955
prefer Export.Context/Session_Context/Theory_Context over Sessions.Database_Context;
 
wenzelm 
parents: 
75775 
diff
changeset
 | 
344  | 
def sessions_structure: Sessions.Structure = session_base_info.sessions_structure  | 
| 
 
d18c96b9b955
prefer Export.Context/Session_Context/Theory_Context over Sessions.Database_Context;
 
wenzelm 
parents: 
75775 
diff
changeset
 | 
345  | 
|
| 
 
d18c96b9b955
prefer Export.Context/Session_Context/Theory_Context over Sessions.Database_Context;
 
wenzelm 
parents: 
75775 
diff
changeset
 | 
346  | 
def session_base: Sessions.Base = session_base_info.base  | 
| 
 
d18c96b9b955
prefer Export.Context/Session_Context/Theory_Context over Sessions.Database_Context;
 
wenzelm 
parents: 
75775 
diff
changeset
 | 
347  | 
|
| 
75770
 
62e2c6f65f9a
clarified Document.Snapshot.all_exports: refer to material from this (virtual) session;
 
wenzelm 
parents: 
75769 
diff
changeset
 | 
348  | 
def session_name: String =  | 
| 
 
62e2c6f65f9a
clarified Document.Snapshot.all_exports: refer to material from this (virtual) session;
 
wenzelm 
parents: 
75769 
diff
changeset
 | 
349  | 
if (document_snapshot.isDefined) Sessions.DRAFT  | 
| 
75773
 
11b2bf6f90d8
clarified signature: less redundant -- Sessions.Base_Info already specifies the main session;
 
wenzelm 
parents: 
75772 
diff
changeset
 | 
350  | 
else session_base.session_name  | 
| 
75770
 
62e2c6f65f9a
clarified Document.Snapshot.all_exports: refer to material from this (virtual) session;
 
wenzelm 
parents: 
75769 
diff
changeset
 | 
351  | 
|
| 
75780
 
f49c4f160b84
clarified signature: find session_database within Session_Context.db_hierarchy;
 
wenzelm 
parents: 
75779 
diff
changeset
 | 
352  | 
def session_database(session: String = session_name): Option[Session_Database] =  | 
| 
 
f49c4f160b84
clarified signature: find session_database within Session_Context.db_hierarchy;
 
wenzelm 
parents: 
75779 
diff
changeset
 | 
353  | 
db_hierarchy.find(_.session == session)  | 
| 
 
f49c4f160b84
clarified signature: find session_database within Session_Context.db_hierarchy;
 
wenzelm 
parents: 
75779 
diff
changeset
 | 
354  | 
|
| 
 
f49c4f160b84
clarified signature: find session_database within Session_Context.db_hierarchy;
 
wenzelm 
parents: 
75779 
diff
changeset
 | 
355  | 
def session_db(session: String = session_name): Option[SQL.Database] =  | 
| 
 
f49c4f160b84
clarified signature: find session_database within Session_Context.db_hierarchy;
 
wenzelm 
parents: 
75779 
diff
changeset
 | 
356  | 
session_database(session = session).map(_.db)  | 
| 
 
f49c4f160b84
clarified signature: find session_database within Session_Context.db_hierarchy;
 
wenzelm 
parents: 
75779 
diff
changeset
 | 
357  | 
|
| 
75770
 
62e2c6f65f9a
clarified Document.Snapshot.all_exports: refer to material from this (virtual) session;
 
wenzelm 
parents: 
75769 
diff
changeset
 | 
358  | 
def session_stack: List[String] =  | 
| 
 
62e2c6f65f9a
clarified Document.Snapshot.all_exports: refer to material from this (virtual) session;
 
wenzelm 
parents: 
75769 
diff
changeset
 | 
359  | 
((if (document_snapshot.isDefined) List(session_name) else Nil) :::  | 
| 
 
62e2c6f65f9a
clarified Document.Snapshot.all_exports: refer to material from this (virtual) session;
 
wenzelm 
parents: 
75769 
diff
changeset
 | 
360  | 
db_hierarchy.map(_.session)).reverse  | 
| 
 
62e2c6f65f9a
clarified Document.Snapshot.all_exports: refer to material from this (virtual) session;
 
wenzelm 
parents: 
75769 
diff
changeset
 | 
361  | 
|
| 
 
62e2c6f65f9a
clarified Document.Snapshot.all_exports: refer to material from this (virtual) session;
 
wenzelm 
parents: 
75769 
diff
changeset
 | 
362  | 
private def select[A](  | 
| 
 
62e2c6f65f9a
clarified Document.Snapshot.all_exports: refer to material from this (virtual) session;
 
wenzelm 
parents: 
75769 
diff
changeset
 | 
363  | 
session: String,  | 
| 
75860
 
2b2c09f4e7b5
proper export theory_names: theory/parents are not necessarily present (amending 4d27b520622a);
 
wenzelm 
parents: 
75825 
diff
changeset
 | 
364  | 
select: Session_Database => List[A],  | 
| 
 
2b2c09f4e7b5
proper export theory_names: theory/parents are not necessarily present (amending 4d27b520622a);
 
wenzelm 
parents: 
75825 
diff
changeset
 | 
365  | 
project: Entry_Name => A,  | 
| 
 
2b2c09f4e7b5
proper export theory_names: theory/parents are not necessarily present (amending 4d27b520622a);
 
wenzelm 
parents: 
75825 
diff
changeset
 | 
366  | 
sort_key: A => String  | 
| 
75770
 
62e2c6f65f9a
clarified Document.Snapshot.all_exports: refer to material from this (virtual) session;
 
wenzelm 
parents: 
75769 
diff
changeset
 | 
367  | 
    ): List[A] = {
 | 
| 
75860
 
2b2c09f4e7b5
proper export theory_names: theory/parents are not necessarily present (amending 4d27b520622a);
 
wenzelm 
parents: 
75825 
diff
changeset
 | 
368  | 
def result(name: String): List[A] =  | 
| 
75770
 
62e2c6f65f9a
clarified Document.Snapshot.all_exports: refer to material from this (virtual) session;
 
wenzelm 
parents: 
75769 
diff
changeset
 | 
369  | 
        if (name == Sessions.DRAFT) {
 | 
| 
 
62e2c6f65f9a
clarified Document.Snapshot.all_exports: refer to material from this (virtual) session;
 
wenzelm 
parents: 
75769 
diff
changeset
 | 
370  | 
          (for {
 | 
| 
 
62e2c6f65f9a
clarified Document.Snapshot.all_exports: refer to material from this (virtual) session;
 
wenzelm 
parents: 
75769 
diff
changeset
 | 
371  | 
snapshot <- document_snapshot.iterator  | 
| 
 
62e2c6f65f9a
clarified Document.Snapshot.all_exports: refer to material from this (virtual) session;
 
wenzelm 
parents: 
75769 
diff
changeset
 | 
372  | 
entry_name <- snapshot.all_exports.keysIterator  | 
| 
75860
 
2b2c09f4e7b5
proper export theory_names: theory/parents are not necessarily present (amending 4d27b520622a);
 
wenzelm 
parents: 
75825 
diff
changeset
 | 
373  | 
} yield project(entry_name)).toSet.toList.sortBy(sort_key)  | 
| 
75770
 
62e2c6f65f9a
clarified Document.Snapshot.all_exports: refer to material from this (virtual) session;
 
wenzelm 
parents: 
75769 
diff
changeset
 | 
374  | 
}  | 
| 
75860
 
2b2c09f4e7b5
proper export theory_names: theory/parents are not necessarily present (amending 4d27b520622a);
 
wenzelm 
parents: 
75825 
diff
changeset
 | 
375  | 
else session_database(name).map(select).getOrElse(Nil)  | 
| 
 
2b2c09f4e7b5
proper export theory_names: theory/parents are not necessarily present (amending 4d27b520622a);
 
wenzelm 
parents: 
75825 
diff
changeset
 | 
376  | 
|
| 
 
2b2c09f4e7b5
proper export theory_names: theory/parents are not necessarily present (amending 4d27b520622a);
 
wenzelm 
parents: 
75825 
diff
changeset
 | 
377  | 
if (session.nonEmpty) result(session) else session_stack.flatMap(result)  | 
| 
75770
 
62e2c6f65f9a
clarified Document.Snapshot.all_exports: refer to material from this (virtual) session;
 
wenzelm 
parents: 
75769 
diff
changeset
 | 
378  | 
}  | 
| 
 
62e2c6f65f9a
clarified Document.Snapshot.all_exports: refer to material from this (virtual) session;
 
wenzelm 
parents: 
75769 
diff
changeset
 | 
379  | 
|
| 
 
62e2c6f65f9a
clarified Document.Snapshot.all_exports: refer to material from this (virtual) session;
 
wenzelm 
parents: 
75769 
diff
changeset
 | 
380  | 
def entry_names(session: String = session_name): List[Entry_Name] =  | 
| 
75860
 
2b2c09f4e7b5
proper export theory_names: theory/parents are not necessarily present (amending 4d27b520622a);
 
wenzelm 
parents: 
75825 
diff
changeset
 | 
381  | 
select(session, _.entry_names, identity, _.compound_name)  | 
| 
75770
 
62e2c6f65f9a
clarified Document.Snapshot.all_exports: refer to material from this (virtual) session;
 
wenzelm 
parents: 
75769 
diff
changeset
 | 
382  | 
|
| 
 
62e2c6f65f9a
clarified Document.Snapshot.all_exports: refer to material from this (virtual) session;
 
wenzelm 
parents: 
75769 
diff
changeset
 | 
383  | 
def theory_names(session: String = session_name): List[String] =  | 
| 
75860
 
2b2c09f4e7b5
proper export theory_names: theory/parents are not necessarily present (amending 4d27b520622a);
 
wenzelm 
parents: 
75825 
diff
changeset
 | 
384  | 
select(session, _.theory_names, _.theory, identity)  | 
| 
75770
 
62e2c6f65f9a
clarified Document.Snapshot.all_exports: refer to material from this (virtual) session;
 
wenzelm 
parents: 
75769 
diff
changeset
 | 
385  | 
|
| 
75759
 
0cdccd0d1699
clarified context for retrieval: more explicit types, with optional close() operation;
 
wenzelm 
parents: 
75757 
diff
changeset
 | 
386  | 
def get(theory: String, name: String): Option[Entry] =  | 
| 
75770
 
62e2c6f65f9a
clarified Document.Snapshot.all_exports: refer to material from this (virtual) session;
 
wenzelm 
parents: 
75769 
diff
changeset
 | 
387  | 
    {
 | 
| 75784 | 388  | 
def snapshot_entry: Option[Entry] =  | 
| 
75770
 
62e2c6f65f9a
clarified Document.Snapshot.all_exports: refer to material from this (virtual) session;
 
wenzelm 
parents: 
75769 
diff
changeset
 | 
389  | 
        for {
 | 
| 
 
62e2c6f65f9a
clarified Document.Snapshot.all_exports: refer to material from this (virtual) session;
 
wenzelm 
parents: 
75769 
diff
changeset
 | 
390  | 
snapshot <- document_snapshot  | 
| 
 
62e2c6f65f9a
clarified Document.Snapshot.all_exports: refer to material from this (virtual) session;
 
wenzelm 
parents: 
75769 
diff
changeset
 | 
391  | 
entry_name = Entry_Name(session = Sessions.DRAFT, theory = theory, name = name)  | 
| 
 
62e2c6f65f9a
clarified Document.Snapshot.all_exports: refer to material from this (virtual) session;
 
wenzelm 
parents: 
75769 
diff
changeset
 | 
392  | 
entry <- snapshot.all_exports.get(entry_name)  | 
| 
 
62e2c6f65f9a
clarified Document.Snapshot.all_exports: refer to material from this (virtual) session;
 
wenzelm 
parents: 
75769 
diff
changeset
 | 
393  | 
} yield entry  | 
| 75784 | 394  | 
def db_entry: Option[Entry] =  | 
395  | 
db_hierarchy.view.map(database =>  | 
|
396  | 
Export.Entry_Name(session = database.session, theory = theory, name = name)  | 
|
397  | 
.read(database.db, cache))  | 
|
| 
75764
 
07e097f60b85
clarified signature: more robust close operation;
 
wenzelm 
parents: 
75762 
diff
changeset
 | 
398  | 
          .collectFirst({ case Some(entry) => entry })
 | 
| 
75759
 
0cdccd0d1699
clarified context for retrieval: more explicit types, with optional close() operation;
 
wenzelm 
parents: 
75757 
diff
changeset
 | 
399  | 
|
| 
75770
 
62e2c6f65f9a
clarified Document.Snapshot.all_exports: refer to material from this (virtual) session;
 
wenzelm 
parents: 
75769 
diff
changeset
 | 
400  | 
snapshot_entry orElse db_entry  | 
| 
 
62e2c6f65f9a
clarified Document.Snapshot.all_exports: refer to material from this (virtual) session;
 
wenzelm 
parents: 
75769 
diff
changeset
 | 
401  | 
}  | 
| 
 
62e2c6f65f9a
clarified Document.Snapshot.all_exports: refer to material from this (virtual) session;
 
wenzelm 
parents: 
75769 
diff
changeset
 | 
402  | 
|
| 
75759
 
0cdccd0d1699
clarified context for retrieval: more explicit types, with optional close() operation;
 
wenzelm 
parents: 
75757 
diff
changeset
 | 
403  | 
def apply(theory: String, name: String, permissive: Boolean = false): Entry =  | 
| 
 
0cdccd0d1699
clarified context for retrieval: more explicit types, with optional close() operation;
 
wenzelm 
parents: 
75757 
diff
changeset
 | 
404  | 
      get(theory, name) match {
 | 
| 
 
0cdccd0d1699
clarified context for retrieval: more explicit types, with optional close() operation;
 
wenzelm 
parents: 
75757 
diff
changeset
 | 
405  | 
case None if permissive => empty_entry(theory, name)  | 
| 
 
0cdccd0d1699
clarified context for retrieval: more explicit types, with optional close() operation;
 
wenzelm 
parents: 
75757 
diff
changeset
 | 
406  | 
        case None => error("Missing export entry " + quote(compound_name(theory, name)))
 | 
| 
 
0cdccd0d1699
clarified context for retrieval: more explicit types, with optional close() operation;
 
wenzelm 
parents: 
75757 
diff
changeset
 | 
407  | 
case Some(entry) => entry  | 
| 
 
0cdccd0d1699
clarified context for retrieval: more explicit types, with optional close() operation;
 
wenzelm 
parents: 
75757 
diff
changeset
 | 
408  | 
}  | 
| 
 
0cdccd0d1699
clarified context for retrieval: more explicit types, with optional close() operation;
 
wenzelm 
parents: 
75757 
diff
changeset
 | 
409  | 
|
| 
75790
 
0ab8a9177e41
clarified signature: more uniform treatment of cache for Export.read_session vs. Export.read_theory;
 
wenzelm 
parents: 
75789 
diff
changeset
 | 
410  | 
def theory(theory: String, other_cache: Option[Term.Cache] = None): Theory_Context =  | 
| 
 
0ab8a9177e41
clarified signature: more uniform treatment of cache for Export.read_session vs. Export.read_theory;
 
wenzelm 
parents: 
75789 
diff
changeset
 | 
411  | 
new Theory_Context(session_context, theory, other_cache)  | 
| 
75759
 
0cdccd0d1699
clarified context for retrieval: more explicit types, with optional close() operation;
 
wenzelm 
parents: 
75757 
diff
changeset
 | 
412  | 
|
| 75825 | 413  | 
    def classpath(): List[File.Content] = {
 | 
| 
75782
 
dba571dd0ba9
clarified signature: prefer Export.Session_Context over Sessions.Database_Context;
 
wenzelm 
parents: 
75780 
diff
changeset
 | 
414  | 
      (for {
 | 
| 
 
dba571dd0ba9
clarified signature: prefer Export.Session_Context over Sessions.Database_Context;
 
wenzelm 
parents: 
75780 
diff
changeset
 | 
415  | 
session <- session_stack.iterator  | 
| 
 
dba571dd0ba9
clarified signature: prefer Export.Session_Context over Sessions.Database_Context;
 
wenzelm 
parents: 
75780 
diff
changeset
 | 
416  | 
info <- sessions_structure.get(session).iterator  | 
| 
 
dba571dd0ba9
clarified signature: prefer Export.Session_Context over Sessions.Database_Context;
 
wenzelm 
parents: 
75780 
diff
changeset
 | 
417  | 
if info.export_classpath.nonEmpty  | 
| 
 
dba571dd0ba9
clarified signature: prefer Export.Session_Context over Sessions.Database_Context;
 
wenzelm 
parents: 
75780 
diff
changeset
 | 
418  | 
matcher = make_matcher(info.export_classpath)  | 
| 
 
dba571dd0ba9
clarified signature: prefer Export.Session_Context over Sessions.Database_Context;
 
wenzelm 
parents: 
75780 
diff
changeset
 | 
419  | 
entry_name <- entry_names(session = session).iterator  | 
| 
 
dba571dd0ba9
clarified signature: prefer Export.Session_Context over Sessions.Database_Context;
 
wenzelm 
parents: 
75780 
diff
changeset
 | 
420  | 
if matcher(entry_name)  | 
| 
 
dba571dd0ba9
clarified signature: prefer Export.Session_Context over Sessions.Database_Context;
 
wenzelm 
parents: 
75780 
diff
changeset
 | 
421  | 
entry <- get(entry_name.theory, entry_name.name).iterator  | 
| 75824 | 422  | 
} yield File.content(entry.entry_name.make_path(), entry.uncompressed)).toList  | 
| 75918 | 423  | 
}  | 
| 
75782
 
dba571dd0ba9
clarified signature: prefer Export.Session_Context over Sessions.Database_Context;
 
wenzelm 
parents: 
75780 
diff
changeset
 | 
424  | 
|
| 75918 | 425  | 
override def toString: String =  | 
| 
75770
 
62e2c6f65f9a
clarified Document.Snapshot.all_exports: refer to material from this (virtual) session;
 
wenzelm 
parents: 
75769 
diff
changeset
 | 
426  | 
      "Export.Session_Context(" + commas_quote(session_stack) + ")"
 | 
| 
75759
 
0cdccd0d1699
clarified context for retrieval: more explicit types, with optional close() operation;
 
wenzelm 
parents: 
75757 
diff
changeset
 | 
427  | 
}  | 
| 
 
0cdccd0d1699
clarified context for retrieval: more explicit types, with optional close() operation;
 
wenzelm 
parents: 
75757 
diff
changeset
 | 
428  | 
|
| 
75774
 
efc25bf4b795
discontinued Export.Provider in favour of Export.Context and its derivatives;
 
wenzelm 
parents: 
75773 
diff
changeset
 | 
429  | 
class Theory_Context private[Export](  | 
| 
 
efc25bf4b795
discontinued Export.Provider in favour of Export.Context and its derivatives;
 
wenzelm 
parents: 
75773 
diff
changeset
 | 
430  | 
val session_context: Session_Context,  | 
| 
75790
 
0ab8a9177e41
clarified signature: more uniform treatment of cache for Export.read_session vs. Export.read_theory;
 
wenzelm 
parents: 
75789 
diff
changeset
 | 
431  | 
val theory: String,  | 
| 
 
0ab8a9177e41
clarified signature: more uniform treatment of cache for Export.read_session vs. Export.read_theory;
 
wenzelm 
parents: 
75789 
diff
changeset
 | 
432  | 
other_cache: Option[Term.Cache]  | 
| 
75774
 
efc25bf4b795
discontinued Export.Provider in favour of Export.Context and its derivatives;
 
wenzelm 
parents: 
75773 
diff
changeset
 | 
433  | 
  ) {
 | 
| 
75790
 
0ab8a9177e41
clarified signature: more uniform treatment of cache for Export.read_session vs. Export.read_theory;
 
wenzelm 
parents: 
75789 
diff
changeset
 | 
434  | 
def cache: Term.Cache = other_cache getOrElse session_context.cache  | 
| 
75778
 
d18c96b9b955
prefer Export.Context/Session_Context/Theory_Context over Sessions.Database_Context;
 
wenzelm 
parents: 
75775 
diff
changeset
 | 
435  | 
|
| 
75759
 
0cdccd0d1699
clarified context for retrieval: more explicit types, with optional close() operation;
 
wenzelm 
parents: 
75757 
diff
changeset
 | 
436  | 
def get(name: String): Option[Entry] = session_context.get(theory, name)  | 
| 
 
0cdccd0d1699
clarified context for retrieval: more explicit types, with optional close() operation;
 
wenzelm 
parents: 
75757 
diff
changeset
 | 
437  | 
def apply(name: String, permissive: Boolean = false): Entry =  | 
| 
 
0cdccd0d1699
clarified context for retrieval: more explicit types, with optional close() operation;
 
wenzelm 
parents: 
75757 
diff
changeset
 | 
438  | 
session_context.apply(theory, name, permissive = permissive)  | 
| 
 
0cdccd0d1699
clarified context for retrieval: more explicit types, with optional close() operation;
 
wenzelm 
parents: 
75757 
diff
changeset
 | 
439  | 
|
| 
75774
 
efc25bf4b795
discontinued Export.Provider in favour of Export.Context and its derivatives;
 
wenzelm 
parents: 
75773 
diff
changeset
 | 
440  | 
def uncompressed_yxml(name: String): XML.Body =  | 
| 
 
efc25bf4b795
discontinued Export.Provider in favour of Export.Context and its derivatives;
 
wenzelm 
parents: 
75773 
diff
changeset
 | 
441  | 
      get(name) match {
 | 
| 
 
efc25bf4b795
discontinued Export.Provider in favour of Export.Context and its derivatives;
 
wenzelm 
parents: 
75773 
diff
changeset
 | 
442  | 
case Some(entry) => entry.uncompressed_yxml  | 
| 
 
efc25bf4b795
discontinued Export.Provider in favour of Export.Context and its derivatives;
 
wenzelm 
parents: 
75773 
diff
changeset
 | 
443  | 
case None => Nil  | 
| 
 
efc25bf4b795
discontinued Export.Provider in favour of Export.Context and its derivatives;
 
wenzelm 
parents: 
75773 
diff
changeset
 | 
444  | 
}  | 
| 
 
efc25bf4b795
discontinued Export.Provider in favour of Export.Context and its derivatives;
 
wenzelm 
parents: 
75773 
diff
changeset
 | 
445  | 
|
| 
75778
 
d18c96b9b955
prefer Export.Context/Session_Context/Theory_Context over Sessions.Database_Context;
 
wenzelm 
parents: 
75775 
diff
changeset
 | 
446  | 
def document_id(): Option[Long] =  | 
| 
 
d18c96b9b955
prefer Export.Context/Session_Context/Theory_Context over Sessions.Database_Context;
 
wenzelm 
parents: 
75775 
diff
changeset
 | 
447  | 
      apply(DOCUMENT_ID, permissive = true).text match {
 | 
| 
 
d18c96b9b955
prefer Export.Context/Session_Context/Theory_Context over Sessions.Database_Context;
 
wenzelm 
parents: 
75775 
diff
changeset
 | 
448  | 
case Value.Long(id) => Some(id)  | 
| 
 
d18c96b9b955
prefer Export.Context/Session_Context/Theory_Context over Sessions.Database_Context;
 
wenzelm 
parents: 
75775 
diff
changeset
 | 
449  | 
case _ => None  | 
| 
 
d18c96b9b955
prefer Export.Context/Session_Context/Theory_Context over Sessions.Database_Context;
 
wenzelm 
parents: 
75775 
diff
changeset
 | 
450  | 
}  | 
| 
 
d18c96b9b955
prefer Export.Context/Session_Context/Theory_Context over Sessions.Database_Context;
 
wenzelm 
parents: 
75775 
diff
changeset
 | 
451  | 
|
| 75901 | 452  | 
def files0(permissive: Boolean = false): List[String] =  | 
453  | 
split_lines(apply(FILES, permissive = permissive).text)  | 
|
454  | 
||
455  | 
def files(permissive: Boolean = false): Option[(String, List[String])] =  | 
|
456  | 
      files0(permissive = permissive) match {
 | 
|
| 
75778
 
d18c96b9b955
prefer Export.Context/Session_Context/Theory_Context over Sessions.Database_Context;
 
wenzelm 
parents: 
75775 
diff
changeset
 | 
457  | 
case Nil => None  | 
| 75901 | 458  | 
case a :: bs => Some((a, bs))  | 
| 
75778
 
d18c96b9b955
prefer Export.Context/Session_Context/Theory_Context over Sessions.Database_Context;
 
wenzelm 
parents: 
75775 
diff
changeset
 | 
459  | 
}  | 
| 
 
d18c96b9b955
prefer Export.Context/Session_Context/Theory_Context over Sessions.Database_Context;
 
wenzelm 
parents: 
75775 
diff
changeset
 | 
460  | 
|
| 
75759
 
0cdccd0d1699
clarified context for retrieval: more explicit types, with optional close() operation;
 
wenzelm 
parents: 
75757 
diff
changeset
 | 
461  | 
    override def toString: String = "Export.Theory_Context(" + quote(theory) + ")"
 | 
| 
 
0cdccd0d1699
clarified context for retrieval: more explicit types, with optional close() operation;
 
wenzelm 
parents: 
75757 
diff
changeset
 | 
462  | 
}  | 
| 
 
0cdccd0d1699
clarified context for retrieval: more explicit types, with optional close() operation;
 
wenzelm 
parents: 
75757 
diff
changeset
 | 
463  | 
|
| 
 
0cdccd0d1699
clarified context for retrieval: more explicit types, with optional close() operation;
 
wenzelm 
parents: 
75757 
diff
changeset
 | 
464  | 
|
| 68288 | 465  | 
/* export to file-system */  | 
466  | 
||
467  | 
def export_files(  | 
|
468  | 
store: Sessions.Store,  | 
|
469  | 
session_name: String,  | 
|
470  | 
export_dir: Path,  | 
|
| 
71726
 
a5fda30edae2
clarified signature: more uniform treatment of stopped/interrupted state;
 
wenzelm 
parents: 
71624 
diff
changeset
 | 
471  | 
progress: Progress = new Progress,  | 
| 69671 | 472  | 
export_prune: Int = 0,  | 
| 68288 | 473  | 
export_list: Boolean = false,  | 
| 75393 | 474  | 
export_patterns: List[String] = Nil  | 
475  | 
  ): Unit = {
 | 
|
| 75394 | 476  | 
    using(store.open_database(session_name)) { db =>
 | 
| 
75739
 
5b37466c1463
removed somewhat pointless transaction: db is meant to be finished (or updated monotonically);
 
wenzelm 
parents: 
75736 
diff
changeset
 | 
477  | 
val entry_names = read_entry_names(db, session_name)  | 
| 68288 | 478  | 
|
| 
75739
 
5b37466c1463
removed somewhat pointless transaction: db is meant to be finished (or updated monotonically);
 
wenzelm 
parents: 
75736 
diff
changeset
 | 
479  | 
// list  | 
| 
 
5b37466c1463
removed somewhat pointless transaction: db is meant to be finished (or updated monotonically);
 
wenzelm 
parents: 
75736 
diff
changeset
 | 
480  | 
      if (export_list) {
 | 
| 
 
5b37466c1463
removed somewhat pointless transaction: db is meant to be finished (or updated monotonically);
 
wenzelm 
parents: 
75736 
diff
changeset
 | 
481  | 
for (entry_name <- entry_names) progress.echo(entry_name.compound_name)  | 
| 
 
5b37466c1463
removed somewhat pointless transaction: db is meant to be finished (or updated monotonically);
 
wenzelm 
parents: 
75736 
diff
changeset
 | 
482  | 
}  | 
| 68288 | 483  | 
|
| 
75739
 
5b37466c1463
removed somewhat pointless transaction: db is meant to be finished (or updated monotonically);
 
wenzelm 
parents: 
75736 
diff
changeset
 | 
484  | 
// export  | 
| 
 
5b37466c1463
removed somewhat pointless transaction: db is meant to be finished (or updated monotonically);
 
wenzelm 
parents: 
75736 
diff
changeset
 | 
485  | 
      if (export_patterns.nonEmpty) {
 | 
| 
 
5b37466c1463
removed somewhat pointless transaction: db is meant to be finished (or updated monotonically);
 
wenzelm 
parents: 
75736 
diff
changeset
 | 
486  | 
val matcher = make_matcher(export_patterns)  | 
| 
 
5b37466c1463
removed somewhat pointless transaction: db is meant to be finished (or updated monotonically);
 
wenzelm 
parents: 
75736 
diff
changeset
 | 
487  | 
        for {
 | 
| 
 
5b37466c1463
removed somewhat pointless transaction: db is meant to be finished (or updated monotonically);
 
wenzelm 
parents: 
75736 
diff
changeset
 | 
488  | 
entry_name <- entry_names if matcher(entry_name)  | 
| 
 
5b37466c1463
removed somewhat pointless transaction: db is meant to be finished (or updated monotonically);
 
wenzelm 
parents: 
75736 
diff
changeset
 | 
489  | 
entry <- entry_name.read(db, store.cache)  | 
| 
 
5b37466c1463
removed somewhat pointless transaction: db is meant to be finished (or updated monotonically);
 
wenzelm 
parents: 
75736 
diff
changeset
 | 
490  | 
        } {
 | 
| 
 
5b37466c1463
removed somewhat pointless transaction: db is meant to be finished (or updated monotonically);
 
wenzelm 
parents: 
75736 
diff
changeset
 | 
491  | 
val path = export_dir + entry_name.make_path(prune = export_prune)  | 
| 
 
5b37466c1463
removed somewhat pointless transaction: db is meant to be finished (or updated monotonically);
 
wenzelm 
parents: 
75736 
diff
changeset
 | 
492  | 
          progress.echo("export " + path + (if (entry.executable) " (executable)" else ""))
 | 
| 
 
5b37466c1463
removed somewhat pointless transaction: db is meant to be finished (or updated monotonically);
 
wenzelm 
parents: 
75736 
diff
changeset
 | 
493  | 
Isabelle_System.make_directory(path.dir)  | 
| 
 
5b37466c1463
removed somewhat pointless transaction: db is meant to be finished (or updated monotonically);
 
wenzelm 
parents: 
75736 
diff
changeset
 | 
494  | 
val bytes = entry.uncompressed  | 
| 
 
5b37466c1463
removed somewhat pointless transaction: db is meant to be finished (or updated monotonically);
 
wenzelm 
parents: 
75736 
diff
changeset
 | 
495  | 
if (!path.is_file || Bytes.read(path) != bytes) Bytes.write(path, bytes)  | 
| 
 
5b37466c1463
removed somewhat pointless transaction: db is meant to be finished (or updated monotonically);
 
wenzelm 
parents: 
75736 
diff
changeset
 | 
496  | 
File.set_executable(path, entry.executable)  | 
| 68288 | 497  | 
}  | 
498  | 
}  | 
|
| 75394 | 499  | 
}  | 
| 68288 | 500  | 
}  | 
501  | 
||
502  | 
||
| 68116 | 503  | 
/* Isabelle tool wrapper */  | 
504  | 
||
| 71601 | 505  | 
  val default_export_dir: Path = Path.explode("export")
 | 
| 68116 | 506  | 
|
| 75394 | 507  | 
val isabelle_tool =  | 
508  | 
    Isabelle_Tool("export", "retrieve theory exports", Scala_Project.here,
 | 
|
509  | 
      { args =>
 | 
|
510  | 
/* arguments */  | 
|
| 68116 | 511  | 
|
| 75394 | 512  | 
var export_dir = default_export_dir  | 
513  | 
var dirs: List[Path] = Nil  | 
|
514  | 
var export_list = false  | 
|
515  | 
var no_build = false  | 
|
516  | 
var options = Options.init()  | 
|
517  | 
var export_prune = 0  | 
|
518  | 
var export_patterns: List[String] = Nil  | 
|
| 68116 | 519  | 
|
| 75394 | 520  | 
        val getopts = Getopts("""
 | 
| 68116 | 521  | 
Usage: isabelle export [OPTIONS] SESSION  | 
522  | 
||
523  | 
Options are:  | 
|
| 
68314
 
2acbf8129d8b
clarified option -O: avoid conflict with build/dump option -D;
 
wenzelm 
parents: 
68305 
diff
changeset
 | 
524  | 
-O DIR output directory for exported files (default: """ + default_export_dir + """)  | 
| 68116 | 525  | 
-d DIR include session directory  | 
526  | 
-l list exports  | 
|
527  | 
-n no build of session  | 
|
528  | 
-o OPTION override Isabelle system OPTION (via NAME=VAL or NAME)  | 
|
| 69671 | 529  | 
-p NUM prune path of exported files by NUM elements  | 
| 68116 | 530  | 
-x PATTERN extract files matching pattern (e.g. "*:**" for all)  | 
531  | 
||
532  | 
List or export theory exports for SESSION: named blobs produced by  | 
|
| 68290 | 533  | 
isabelle build. Option -l or -x is required; option -x may be repeated.  | 
| 68116 | 534  | 
|
535  | 
The PATTERN language resembles glob patterns in the shell, with ? and *  | 
|
536  | 
(both excluding ":" and "/"), ** (excluding ":"), and [abc] or [^abc],  | 
|
537  | 
  and variants {pattern1,pattern2,pattern3}.
 | 
|
538  | 
""",  | 
|
| 75394 | 539  | 
"O:" -> (arg => export_dir = Path.explode(arg)),  | 
540  | 
"d:" -> (arg => dirs = dirs ::: List(Path.explode(arg))),  | 
|
541  | 
"l" -> (_ => export_list = true),  | 
|
542  | 
"n" -> (_ => no_build = true),  | 
|
543  | 
"o:" -> (arg => options = options + arg),  | 
|
544  | 
"p:" -> (arg => export_prune = Value.Int.parse(arg)),  | 
|
545  | 
"x:" -> (arg => export_patterns ::= arg))  | 
|
| 68116 | 546  | 
|
| 75394 | 547  | 
val more_args = getopts(args)  | 
548  | 
val session_name =  | 
|
549  | 
          more_args match {
 | 
|
550  | 
case List(session_name) if export_list || export_patterns.nonEmpty => session_name  | 
|
551  | 
case _ => getopts.usage()  | 
|
552  | 
}  | 
|
| 68116 | 553  | 
|
| 75394 | 554  | 
val progress = new Console_Progress()  | 
| 68305 | 555  | 
|
| 68116 | 556  | 
|
| 75394 | 557  | 
/* build */  | 
| 68116 | 558  | 
|
| 75394 | 559  | 
        if (!no_build) {
 | 
560  | 
val rc =  | 
|
561  | 
            progress.interrupt_handler {
 | 
|
562  | 
Build.build_logic(options, session_name, progress = progress, dirs = dirs)  | 
|
563  | 
}  | 
|
564  | 
if (rc != Process_Result.RC.ok) sys.exit(rc)  | 
|
| 68331 | 565  | 
}  | 
| 68116 | 566  | 
|
567  | 
||
| 75394 | 568  | 
/* export files */  | 
| 68116 | 569  | 
|
| 75394 | 570  | 
val store = Sessions.store(options)  | 
571  | 
export_files(store, session_name, export_dir, progress = progress, export_prune = export_prune,  | 
|
572  | 
export_list = export_list, export_patterns = export_patterns)  | 
|
573  | 
})  | 
|
| 
68092
 
888d35a19866
store exports in session database, with asynchronous / parallel compression;
 
wenzelm 
parents:  
diff
changeset
 | 
574  | 
}  |