src/Pure/Thy/export.scala
author wenzelm
Tue, 08 May 2018 15:41:52 +0200
changeset 68115 23c6ae3dd3a0
parent 68104 3795f67716e6
child 68116 ac82ee617a75
permissions -rw-r--r--
more efficient query;
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
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
     9
object Export
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    10
{
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    11
  /* SQL data model */
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    12
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    13
  object Data
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    14
  {
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    15
    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
    16
    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
    17
    val name = SQL.Column.string("name").make_primary_key
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    18
    val compressed = SQL.Column.bool("compressed")
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    19
    val body = SQL.Column.bytes("body")
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    20
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    21
    val table =
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    22
      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
    23
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    24
    def where_equal(session_name: String, theory_name: String): SQL.Source =
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    25
      "WHERE " + Data.session_name.equal(session_name) +
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    26
      " AND " + Data.theory_name.equal(theory_name)
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    27
  }
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    28
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    29
  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
    30
  {
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    31
    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
    32
    db.using_statement(select)(stmt =>
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    33
      stmt.execute_query().iterator(res => res.string(Data.name)).toList)
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    34
  }
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    35
68115
23c6ae3dd3a0 more efficient query;
wenzelm
parents: 68104
diff changeset
    36
  def read_name(db: SQL.Database, session_name: String, theory_name: String, name: String): Boolean =
23c6ae3dd3a0 more efficient query;
wenzelm
parents: 68104
diff changeset
    37
  {
23c6ae3dd3a0 more efficient query;
wenzelm
parents: 68104
diff changeset
    38
    val select =
23c6ae3dd3a0 more efficient query;
wenzelm
parents: 68104
diff changeset
    39
      Data.table.select(List(Data.name),
23c6ae3dd3a0 more efficient query;
wenzelm
parents: 68104
diff changeset
    40
        Data.where_equal(session_name, theory_name) + " AND " + Data.name.equal(name))
23c6ae3dd3a0 more efficient query;
wenzelm
parents: 68104
diff changeset
    41
    db.using_statement(select)(stmt => stmt.execute_query().next())
23c6ae3dd3a0 more efficient query;
wenzelm
parents: 68104
diff changeset
    42
  }
23c6ae3dd3a0 more efficient query;
wenzelm
parents: 68104
diff changeset
    43
68104
wenzelm
parents: 68103
diff changeset
    44
  def message(msg: String, theory_name: String, name: String): String =
wenzelm
parents: 68103
diff changeset
    45
    msg + " " + quote(name) + " for theory " + quote(theory_name)
wenzelm
parents: 68103
diff changeset
    46
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    47
  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
    48
    session_name: String,
c5764b8b2a87 more robust (synchronous) management of Export.Entry: Future.fork happens inside the data structure;
wenzelm
parents: 68102
diff changeset
    49
    theory_name: String,
c5764b8b2a87 more robust (synchronous) management of Export.Entry: Future.fork happens inside the data structure;
wenzelm
parents: 68102
diff changeset
    50
    name: String,
c5764b8b2a87 more robust (synchronous) management of Export.Entry: Future.fork happens inside the data structure;
wenzelm
parents: 68102
diff changeset
    51
    compressed: Boolean,
c5764b8b2a87 more robust (synchronous) management of Export.Entry: Future.fork happens inside the data structure;
wenzelm
parents: 68102
diff changeset
    52
    body: Future[Bytes])
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    53
  {
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    54
    override def toString: String = theory_name + ":" + name
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    55
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    56
    def write(db: SQL.Database)
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    57
    {
68103
c5764b8b2a87 more robust (synchronous) management of Export.Entry: Future.fork happens inside the data structure;
wenzelm
parents: 68102
diff changeset
    58
      val bytes = body.join
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    59
      db.using_statement(Data.table.insert())(stmt =>
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    60
      {
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    61
        stmt.string(1) = session_name
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    62
        stmt.string(2) = theory_name
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    63
        stmt.string(3) = name
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    64
        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
    65
        stmt.bytes(5) = bytes
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    66
        stmt.execute()
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    67
      })
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    68
    }
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    69
  }
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    70
68101
0699a0bacc50 store exports within PIDE command state;
wenzelm
parents: 68092
diff changeset
    71
  def make_entry(session_name: String, args: Markup.Export.Args, body: Bytes): Entry =
0699a0bacc50 store exports within PIDE command state;
wenzelm
parents: 68092
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
    Entry(session_name, args.theory_name, args.name, args.compress,
c5764b8b2a87 more robust (synchronous) management of Export.Entry: Future.fork happens inside the data structure;
wenzelm
parents: 68102
diff changeset
    74
      if (args.compress) Future.fork(body.compress()) else Future.value(body))
68101
0699a0bacc50 store exports within PIDE command state;
wenzelm
parents: 68092
diff changeset
    75
  }
0699a0bacc50 store exports within PIDE command state;
wenzelm
parents: 68092
diff changeset
    76
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    77
  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
    78
  {
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    79
    val select =
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    80
      Data.table.select(List(Data.compressed, Data.body),
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    81
        Data.where_equal(session_name, theory_name) + " AND " + Data.name.equal(name))
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    82
    db.using_statement(select)(stmt =>
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    83
    {
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    84
      val res = stmt.execute_query()
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    85
      if (res.next()) {
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    86
        val compressed = res.bool(Data.compressed)
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    87
        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
    88
        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
    89
      }
68104
wenzelm
parents: 68103
diff changeset
    90
      else error(message("Bad export", theory_name, name))
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    91
    })
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    92
  }
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    93
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    94
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    95
  /* database consumer thread */
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    96
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    97
  def consumer(db: SQL.Database): Consumer = new Consumer(db)
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    98
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
    99
  class Consumer private[Export](db: SQL.Database)
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   100
  {
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   101
    db.create_table(Data.table)
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   102
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   103
    private val export_errors = Synchronized[List[String]](Nil)
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   104
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   105
    private val consumer =
68103
c5764b8b2a87 more robust (synchronous) management of Export.Entry: Future.fork happens inside the data structure;
wenzelm
parents: 68102
diff changeset
   106
      Consumer_Thread.fork(name = "export")(consume = (entry: Entry) =>
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   107
        {
68103
c5764b8b2a87 more robust (synchronous) management of Export.Entry: Future.fork happens inside the data structure;
wenzelm
parents: 68102
diff changeset
   108
          entry.body.join
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   109
          db.transaction {
68115
23c6ae3dd3a0 more efficient query;
wenzelm
parents: 68104
diff changeset
   110
            if (read_name(db, entry.session_name, entry.theory_name, entry.name)) {
68104
wenzelm
parents: 68103
diff changeset
   111
              val err = message("Duplicate export", entry.theory_name, entry.name)
wenzelm
parents: 68103
diff changeset
   112
              export_errors.change(errs => err :: errs)
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   113
            }
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   114
            else entry.write(db)
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   115
          }
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   116
          true
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   117
        })
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   118
68103
c5764b8b2a87 more robust (synchronous) management of Export.Entry: Future.fork happens inside the data structure;
wenzelm
parents: 68102
diff changeset
   119
    def apply(session_name: String, args: Markup.Export.Args, body: Bytes): Unit =
c5764b8b2a87 more robust (synchronous) management of Export.Entry: Future.fork happens inside the data structure;
wenzelm
parents: 68102
diff changeset
   120
      consumer.send(make_entry(session_name, args, body))
68092
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   121
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   122
    def shutdown(close: Boolean = false): List[String] =
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   123
    {
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   124
      consumer.shutdown()
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   125
      if (close) db.close()
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   126
      export_errors.value.reverse
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
  }
888d35a19866 store exports in session database, with asynchronous / parallel compression;
wenzelm
parents:
diff changeset
   129
}