src/Pure/Thy/export.scala
author wenzelm
Sun, 13 May 2018 16:05:29 +0200
changeset 68166 021c6fecaf5c
parent 68151 3c321783bae3
child 68167 327bb0f5f768
permissions -rw-r--r--
tuned -- use XZ.Cache;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
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
813b5d0904c6 clarified signature;
wenzelm
parents: 68101
diff changeset
     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
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
     9
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    10
import scala.annotation.tailrec
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    11
import scala.util.matching.Regex
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    12
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    13
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    14
object Export
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    15
{
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    16
  /* SQL data model */
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    17
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    18
  object Data
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    19
  {
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    20
    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
    21
    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
    22
    val name = SQL.Column.string("name").make_primary_key
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    23
    val compressed = SQL.Column.bool("compressed")
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    24
    val body = SQL.Column.bytes("body")
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    25
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    26
    val table =
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    27
      SQL.Table("isabelle_exports", List(session_name, theory_name, name, compressed, body))
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    28
68116
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    29
    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
    30
      "WHERE " + Data.session_name.equal(session_name) +
68116
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    31
        (if (theory_name == "") "" else " AND " + Data.theory_name.equal(theory_name)) +
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    32
        (if (name == "") "" else " AND " + Data.name.equal(name))
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    33
  }
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    34
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    35
  def read_name(db: SQL.Database, session_name: String, theory_name: String, name: String): Boolean =
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    36
  {
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    37
    val select =
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    38
      Data.table.select(List(Data.name), Data.where_equal(session_name, theory_name, name))
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    39
    db.using_statement(select)(stmt => stmt.execute_query().next())
68092
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
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    42
  def read_names(db: SQL.Database, session_name: String, theory_name: String): List[String] =
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    43
  {
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    44
    val select = Data.table.select(List(Data.name), Data.where_equal(session_name, theory_name))
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    45
    db.using_statement(select)(stmt =>
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    46
      stmt.execute_query().iterator(res => res.string(Data.name)).toList)
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    47
  }
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    48
68116
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    49
  def read_theory_names(db: SQL.Database, session_name: String): List[(String, String)] =
68115
23c6ae3dd3a0 more efficient query;
wenzelm
parents: 68104
diff changeset
    50
  {
68116
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    51
    val select = Data.table.select(List(Data.theory_name, Data.name), Data.where_equal(session_name))
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    52
    db.using_statement(select)(stmt =>
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    53
      stmt.execute_query().iterator(res =>
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    54
        (res.string(Data.theory_name), res.string(Data.name))).toList)
68115
23c6ae3dd3a0 more efficient query;
wenzelm
parents: 68104
diff changeset
    55
  }
23c6ae3dd3a0 more efficient query;
wenzelm
parents: 68104
diff changeset
    56
68104
wenzelm
parents: 68103
diff changeset
    57
  def message(msg: String, theory_name: String, name: String): String =
wenzelm
parents: 68103
diff changeset
    58
    msg + " " + quote(name) + " for theory " + quote(theory_name)
wenzelm
parents: 68103
diff changeset
    59
68116
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    60
  def compound_name(a: String, b: String): String = a + ":" + b
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    61
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    62
  sealed case class Entry(
68103
c5764b8b2a87 more robust (synchronous) management of Export.Entry: Future.fork happens inside the data structure;
wenzelm
parents: 68102
diff changeset
    63
    session_name: String,
c5764b8b2a87 more robust (synchronous) management of Export.Entry: Future.fork happens inside the data structure;
wenzelm
parents: 68102
diff changeset
    64
    theory_name: String,
c5764b8b2a87 more robust (synchronous) management of Export.Entry: Future.fork happens inside the data structure;
wenzelm
parents: 68102
diff changeset
    65
    name: String,
c5764b8b2a87 more robust (synchronous) management of Export.Entry: Future.fork happens inside the data structure;
wenzelm
parents: 68102
diff changeset
    66
    compressed: Boolean,
c5764b8b2a87 more robust (synchronous) management of Export.Entry: Future.fork happens inside the data structure;
wenzelm
parents: 68102
diff changeset
    67
    body: Future[Bytes])
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    68
  {
68116
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    69
    override def toString: String = compound_name(theory_name, name)
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    70
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    71
    def write(db: SQL.Database)
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    72
    {
68103
c5764b8b2a87 more robust (synchronous) management of Export.Entry: Future.fork happens inside the data structure;
wenzelm
parents: 68102
diff changeset
    73
      val bytes = body.join
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    74
      db.using_statement(Data.table.insert())(stmt =>
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    75
      {
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    76
        stmt.string(1) = session_name
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    77
        stmt.string(2) = theory_name
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    78
        stmt.string(3) = name
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    79
        stmt.bool(4) = compressed
68103
c5764b8b2a87 more robust (synchronous) management of Export.Entry: Future.fork happens inside the data structure;
wenzelm
parents: 68102
diff changeset
    80
        stmt.bytes(5) = bytes
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    81
        stmt.execute()
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    82
      })
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    83
    }
68116
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    84
68166
021c6fecaf5c tuned -- use XZ.Cache;
wenzelm
parents: 68151
diff changeset
    85
    def body_uncompressed(cache: XZ.Cache = XZ.cache()): Bytes =
021c6fecaf5c tuned -- use XZ.Cache;
wenzelm
parents: 68151
diff changeset
    86
      if (compressed) body.join.uncompress(cache = cache) else body.join
68116
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    87
  }
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    88
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    89
  def make_regex(pattern: String): Regex =
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    90
  {
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    91
    @tailrec def make(result: List[String], depth: Int, chs: List[Char]): Regex =
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    92
      chs match {
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    93
        case '*' :: '*' :: rest => make("[^:]*" :: result, depth, rest)
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    94
        case '*' :: rest => make("[^:/]*" :: result, depth, rest)
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    95
        case '?' :: rest => make("[^:/]" :: result, depth, rest)
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    96
        case '\\' :: c :: rest => make(("\\" + c) :: result, depth, rest)
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    97
        case '{' :: rest => make("(" :: result, depth + 1, rest)
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    98
        case ',' :: rest if depth > 0 => make("|" :: result, depth, rest)
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
    99
        case '}' :: rest if depth > 0 => make(")" :: result, depth - 1, rest)
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   100
        case c :: rest if ".+()".contains(c) => make(("\\" + c) :: result, depth, rest)
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   101
        case c :: rest => make(c.toString :: result, depth, rest)
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   102
        case Nil => result.reverse.mkString.r
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   103
      }
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   104
    make(Nil, 0, pattern.toList)
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   105
  }
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   106
68151
wenzelm
parents: 68116
diff changeset
   107
  def make_matcher(pattern: String): (String, String) => Boolean =
wenzelm
parents: 68116
diff changeset
   108
  {
wenzelm
parents: 68116
diff changeset
   109
    val regex = make_regex(pattern)
wenzelm
parents: 68116
diff changeset
   110
    (theory_name: String, name: String) =>
wenzelm
parents: 68116
diff changeset
   111
      regex.pattern.matcher(compound_name(theory_name, name)).matches
wenzelm
parents: 68116
diff changeset
   112
  }
wenzelm
parents: 68116
diff changeset
   113
68166
021c6fecaf5c tuned -- use XZ.Cache;
wenzelm
parents: 68151
diff changeset
   114
  def make_entry(session_name: String, args: Markup.Export.Args, body: Bytes,
021c6fecaf5c tuned -- use XZ.Cache;
wenzelm
parents: 68151
diff changeset
   115
    cache: XZ.Cache = XZ.cache()): Entry =
68101
0699a0bacc50 store exports within PIDE command state;
wenzelm
parents: 68092
diff changeset
   116
  {
68103
c5764b8b2a87 more robust (synchronous) management of Export.Entry: Future.fork happens inside the data structure;
wenzelm
parents: 68102
diff changeset
   117
    Entry(session_name, args.theory_name, args.name, args.compress,
68166
021c6fecaf5c tuned -- use XZ.Cache;
wenzelm
parents: 68151
diff changeset
   118
      if (args.compress) Future.fork(body.compress(cache = cache)) else Future.value(body))
68101
0699a0bacc50 store exports within PIDE command state;
wenzelm
parents: 68092
diff changeset
   119
  }
0699a0bacc50 store exports within PIDE command state;
wenzelm
parents: 68092
diff changeset
   120
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   121
  def read_entry(db: SQL.Database, session_name: String, theory_name: String, name: String): Entry =
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   122
  {
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   123
    val select =
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   124
      Data.table.select(List(Data.compressed, Data.body),
68116
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   125
        Data.where_equal(session_name, theory_name, name))
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   126
    db.using_statement(select)(stmt =>
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   127
    {
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   128
      val res = stmt.execute_query()
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   129
      if (res.next()) {
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   130
        val compressed = res.bool(Data.compressed)
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   131
        val body = res.bytes(Data.body)
68103
c5764b8b2a87 more robust (synchronous) management of Export.Entry: Future.fork happens inside the data structure;
wenzelm
parents: 68102
diff changeset
   132
        Entry(session_name, theory_name, name, compressed, Future.value(body))
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   133
      }
68104
wenzelm
parents: 68103
diff changeset
   134
      else error(message("Bad export", theory_name, name))
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   135
    })
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   136
  }
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   137
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   138
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   139
  /* database consumer thread */
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   140
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   141
  def consumer(db: SQL.Database): Consumer = new Consumer(db)
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   142
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   143
  class Consumer private[Export](db: SQL.Database)
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   144
  {
68166
021c6fecaf5c tuned -- use XZ.Cache;
wenzelm
parents: 68151
diff changeset
   145
    val xz_cache = XZ.make_cache()
021c6fecaf5c tuned -- use XZ.Cache;
wenzelm
parents: 68151
diff changeset
   146
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   147
    db.create_table(Data.table)
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   148
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   149
    private val export_errors = Synchronized[List[String]](Nil)
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   150
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   151
    private val consumer =
68103
c5764b8b2a87 more robust (synchronous) management of Export.Entry: Future.fork happens inside the data structure;
wenzelm
parents: 68102
diff changeset
   152
      Consumer_Thread.fork(name = "export")(consume = (entry: Entry) =>
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   153
        {
68103
c5764b8b2a87 more robust (synchronous) management of Export.Entry: Future.fork happens inside the data structure;
wenzelm
parents: 68102
diff changeset
   154
          entry.body.join
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   155
          db.transaction {
68115
23c6ae3dd3a0 more efficient query;
wenzelm
parents: 68104
diff changeset
   156
            if (read_name(db, entry.session_name, entry.theory_name, entry.name)) {
68104
wenzelm
parents: 68103
diff changeset
   157
              val err = message("Duplicate export", entry.theory_name, entry.name)
wenzelm
parents: 68103
diff changeset
   158
              export_errors.change(errs => err :: errs)
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   159
            }
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   160
            else entry.write(db)
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   161
          }
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   162
          true
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   163
        })
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   164
68103
c5764b8b2a87 more robust (synchronous) management of Export.Entry: Future.fork happens inside the data structure;
wenzelm
parents: 68102
diff changeset
   165
    def apply(session_name: String, args: Markup.Export.Args, body: Bytes): Unit =
68166
021c6fecaf5c tuned -- use XZ.Cache;
wenzelm
parents: 68151
diff changeset
   166
      consumer.send(make_entry(session_name, args, body, cache = xz_cache))
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   167
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   168
    def shutdown(close: Boolean = false): List[String] =
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   169
    {
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   170
      consumer.shutdown()
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   171
      if (close) db.close()
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   172
      export_errors.value.reverse
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   173
    }
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   174
  }
68116
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   175
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   176
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   177
  /* Isabelle tool wrapper */
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   178
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   179
  val default_export_dir = Path.explode("export")
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   180
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   181
  val isabelle_tool = Isabelle_Tool("export", "retrieve theory exports", args =>
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   182
  {
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   183
    /* arguments */
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   184
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   185
    var export_dir = default_export_dir
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   186
    var dirs: List[Path] = Nil
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   187
    var export_list = false
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   188
    var no_build = false
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   189
    var options = Options.init()
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   190
    var system_mode = false
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   191
    var export_pattern = ""
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   192
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   193
    val getopts = Getopts("""
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   194
Usage: isabelle export [OPTIONS] SESSION
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   195
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   196
  Options are:
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   197
    -D DIR       target directory for exported files (default: """ + default_export_dir + """)
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   198
    -d DIR       include session directory
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   199
    -l           list exports
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   200
    -n           no build of session
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   201
    -o OPTION    override Isabelle system OPTION (via NAME=VAL or NAME)
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   202
    -s           system build mode for session image
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   203
    -x PATTERN   extract files matching pattern (e.g. "*:**" for all)
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   204
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   205
  List or export theory exports for SESSION: named blobs produced by
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   206
  isabelle build. Option -l or -x is required.
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   207
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   208
  The PATTERN language resembles glob patterns in the shell, with ? and *
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   209
  (both excluding ":" and "/"), ** (excluding ":"), and [abc] or [^abc],
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   210
  and variants {pattern1,pattern2,pattern3}.
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   211
""",
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   212
      "D:" -> (arg => export_dir = Path.explode(arg)),
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   213
      "d:" -> (arg => dirs = dirs ::: List(Path.explode(arg))),
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   214
      "l" -> (_ => export_list = true),
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   215
      "n" -> (_ => no_build = true),
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   216
      "o:" -> (arg => options = options + arg),
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   217
      "s" -> (_ => system_mode = true),
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   218
      "x:" -> (arg => export_pattern = arg))
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   219
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   220
    val more_args = getopts(args)
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   221
    val session_name =
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   222
      more_args match {
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   223
        case List(session_name) if export_list || export_pattern != "" => session_name
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   224
        case _ => getopts.usage()
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   225
      }
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   226
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   227
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   228
    /* build */
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   229
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   230
    val progress = new Console_Progress()
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   231
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   232
    if (!no_build &&
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   233
        !Build.build(options, no_build = true, dirs = dirs, system_mode = system_mode,
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   234
          sessions = List(session_name)).ok)
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   235
    {
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   236
      progress.echo("Build started for Isabelle/" + session_name + " ...")
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   237
      progress.interrupt_handler {
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   238
        val res =
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   239
          Build.build(options, progress = progress, dirs = dirs, system_mode = system_mode,
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   240
            sessions = List(session_name))
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   241
        if (!res.ok) sys.exit(res.rc)
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   242
      }
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   243
    }
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   244
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   245
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   246
    /* database */
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   247
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   248
    val store = Sessions.store(system_mode)
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   249
    val database =
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   250
      store.find_database(session_name) match {
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   251
        case None => error("Missing database for session " + quote(session_name))
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   252
        case Some(database) => database
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   253
      }
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   254
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   255
    using(SQLite.open_database(database))(db =>
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   256
    {
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   257
      db.transaction {
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   258
        val export_names = read_theory_names(db, session_name)
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   259
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   260
        // list
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   261
        if (export_list) {
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   262
          (for ((theory_name, name) <- export_names) yield compound_name(theory_name, name)).
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   263
            sorted.foreach(Output.writeln(_, stdout = true))
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   264
        }
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   265
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   266
        // export
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   267
        if (export_pattern != "") {
68166
021c6fecaf5c tuned -- use XZ.Cache;
wenzelm
parents: 68151
diff changeset
   268
          val xz_cache = XZ.make_cache()
021c6fecaf5c tuned -- use XZ.Cache;
wenzelm
parents: 68151
diff changeset
   269
68151
wenzelm
parents: 68116
diff changeset
   270
          val matcher = make_matcher(export_pattern)
wenzelm
parents: 68116
diff changeset
   271
          for { (theory_name, name) <- export_names if matcher(theory_name, name) }
wenzelm
parents: 68116
diff changeset
   272
          {
68116
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   273
            val entry = read_entry(db, session_name, theory_name, name)
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   274
            val path = export_dir + Path.basic(theory_name) + Path.explode(name)
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   275
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   276
            progress.echo("exporting " + path)
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   277
            Isabelle_System.mkdirs(path.dir)
68166
021c6fecaf5c tuned -- use XZ.Cache;
wenzelm
parents: 68151
diff changeset
   278
            Bytes.write(path, entry.body_uncompressed(cache = xz_cache))
68116
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   279
          }
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   280
        }
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   281
      }
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   282
    })
ac82ee617a75 command-line tool "isabelle export";
wenzelm
parents: 68115
diff changeset
   283
  })
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   284
}