src/Pure/ML/ml_heap.scala
author wenzelm
Thu, 10 Aug 2023 19:58:23 +0200
changeset 78509 146468e05dd4
parent 78396 7853d9072d1b
child 78510 8f45302a9ff0
permissions -rw-r--r--
more robust: atomic file-system result via tmp file;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
76991
6a078c80eab6 clarified modules;
wenzelm
parents:
diff changeset
     1
/*  Title:      Pure/ML/ml_heap.scala
6a078c80eab6 clarified modules;
wenzelm
parents:
diff changeset
     2
    Author:     Makarius
6a078c80eab6 clarified modules;
wenzelm
parents:
diff changeset
     3
6a078c80eab6 clarified modules;
wenzelm
parents:
diff changeset
     4
ML heap operations.
6a078c80eab6 clarified modules;
wenzelm
parents:
diff changeset
     5
*/
6a078c80eab6 clarified modules;
wenzelm
parents:
diff changeset
     6
6a078c80eab6 clarified modules;
wenzelm
parents:
diff changeset
     7
package isabelle
6a078c80eab6 clarified modules;
wenzelm
parents:
diff changeset
     8
6a078c80eab6 clarified modules;
wenzelm
parents:
diff changeset
     9
6a078c80eab6 clarified modules;
wenzelm
parents:
diff changeset
    10
import java.nio.ByteBuffer
6a078c80eab6 clarified modules;
wenzelm
parents:
diff changeset
    11
import java.nio.channels.FileChannel
6a078c80eab6 clarified modules;
wenzelm
parents:
diff changeset
    12
import java.nio.file.StandardOpenOption
6a078c80eab6 clarified modules;
wenzelm
parents:
diff changeset
    13
6a078c80eab6 clarified modules;
wenzelm
parents:
diff changeset
    14
6a078c80eab6 clarified modules;
wenzelm
parents:
diff changeset
    15
object ML_Heap {
6a078c80eab6 clarified modules;
wenzelm
parents:
diff changeset
    16
  /** heap file with SHA1 digest **/
6a078c80eab6 clarified modules;
wenzelm
parents:
diff changeset
    17
6a078c80eab6 clarified modules;
wenzelm
parents:
diff changeset
    18
  private val sha1_prefix = "SHA1:"
6a078c80eab6 clarified modules;
wenzelm
parents:
diff changeset
    19
78182
31835adf148a tuned signature;
wenzelm
parents: 77720
diff changeset
    20
  def read_file_digest(heap: Path): Option[SHA1.Digest] = {
76991
6a078c80eab6 clarified modules;
wenzelm
parents:
diff changeset
    21
    if (heap.is_file) {
77711
25fd62cba347 clarified signature: more general operation Bytes.read_slice;
wenzelm
parents: 77206
diff changeset
    22
      val l = sha1_prefix.length
25fd62cba347 clarified signature: more general operation Bytes.read_slice;
wenzelm
parents: 77206
diff changeset
    23
      val m = l + SHA1.digest_length
25fd62cba347 clarified signature: more general operation Bytes.read_slice;
wenzelm
parents: 77206
diff changeset
    24
      val n = heap.file.length
77718
6ad3a412ed97 clarified signature;
wenzelm
parents: 77711
diff changeset
    25
      val bs = Bytes.read_file(heap.file, offset = n - m)
77711
25fd62cba347 clarified signature: more general operation Bytes.read_slice;
wenzelm
parents: 77206
diff changeset
    26
      if (bs.length == m) {
25fd62cba347 clarified signature: more general operation Bytes.read_slice;
wenzelm
parents: 77206
diff changeset
    27
        val s = bs.text
25fd62cba347 clarified signature: more general operation Bytes.read_slice;
wenzelm
parents: 77206
diff changeset
    28
        if (s.startsWith(sha1_prefix)) Some(SHA1.fake_digest(s.substring(l)))
76991
6a078c80eab6 clarified modules;
wenzelm
parents:
diff changeset
    29
        else None
6a078c80eab6 clarified modules;
wenzelm
parents:
diff changeset
    30
      }
77711
25fd62cba347 clarified signature: more general operation Bytes.read_slice;
wenzelm
parents: 77206
diff changeset
    31
      else None
76991
6a078c80eab6 clarified modules;
wenzelm
parents:
diff changeset
    32
    }
6a078c80eab6 clarified modules;
wenzelm
parents:
diff changeset
    33
    else None
6a078c80eab6 clarified modules;
wenzelm
parents:
diff changeset
    34
  }
6a078c80eab6 clarified modules;
wenzelm
parents:
diff changeset
    35
78182
31835adf148a tuned signature;
wenzelm
parents: 77720
diff changeset
    36
  def write_file_digest(heap: Path): SHA1.Digest =
31835adf148a tuned signature;
wenzelm
parents: 77720
diff changeset
    37
    read_file_digest(heap) getOrElse {
77206
6784eaef7d0c prefer explicit shasum;
wenzelm
parents: 76992
diff changeset
    38
      val digest = SHA1.digest(heap)
6784eaef7d0c prefer explicit shasum;
wenzelm
parents: 76992
diff changeset
    39
      File.append(heap, sha1_prefix + digest.toString)
6784eaef7d0c prefer explicit shasum;
wenzelm
parents: 76992
diff changeset
    40
      digest
76991
6a078c80eab6 clarified modules;
wenzelm
parents:
diff changeset
    41
    }
77720
f750047e9386 tuned comments;
wenzelm
parents: 77718
diff changeset
    42
f750047e9386 tuned comments;
wenzelm
parents: 77718
diff changeset
    43
f750047e9386 tuned comments;
wenzelm
parents: 77718
diff changeset
    44
  /* SQL data model */
f750047e9386 tuned comments;
wenzelm
parents: 77718
diff changeset
    45
78396
7853d9072d1b renamed object Data to private_data, to emphasize its intended scope (but it is publicly accessible in the database);
wenzelm
parents: 78369
diff changeset
    46
  object private_data extends SQL.Data("isabelle_heaps") {
78187
2df0f3604a67 clarified signature: more explicit class SQL.Data;
wenzelm
parents: 78186
diff changeset
    47
    override lazy val tables = SQL.Tables(Base.table, Slices.table)
78183
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    48
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    49
    object Generic {
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    50
      val name = SQL.Column.string("name").make_primary_key
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    51
    }
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    52
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    53
    object Base {
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    54
      val name = Generic.name
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    55
      val size = SQL.Column.long("size")
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    56
      val digest = SQL.Column.string("digest")
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    57
78266
d8c99a497502 clarified signature;
wenzelm
parents: 78213
diff changeset
    58
      val table = make_table(List(name, size, digest))
78183
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    59
    }
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    60
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    61
    object Slices {
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    62
      val name = Generic.name
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    63
      val slice = SQL.Column.int("slice").make_primary_key
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    64
      val content = SQL.Column.bytes("content")
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    65
78266
d8c99a497502 clarified signature;
wenzelm
parents: 78213
diff changeset
    66
      val table = make_table(List(name, slice, content), name = "slices")
78183
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    67
    }
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    68
78278
5717310a0c6a create database view for diagnostic purposes;
wenzelm
parents: 78266
diff changeset
    69
    object Slices_Size {
5717310a0c6a create database view for diagnostic purposes;
wenzelm
parents: 78266
diff changeset
    70
      val name = Generic.name
5717310a0c6a create database view for diagnostic purposes;
wenzelm
parents: 78266
diff changeset
    71
      val slice = SQL.Column.int("slice").make_primary_key
5717310a0c6a create database view for diagnostic purposes;
wenzelm
parents: 78266
diff changeset
    72
      val size = SQL.Column.long("size")
5717310a0c6a create database view for diagnostic purposes;
wenzelm
parents: 78266
diff changeset
    73
5717310a0c6a create database view for diagnostic purposes;
wenzelm
parents: 78266
diff changeset
    74
      val table = make_table(List(name, slice, size),
5717310a0c6a create database view for diagnostic purposes;
wenzelm
parents: 78266
diff changeset
    75
        body = "SELECT name, slice, pg_size_pretty(length(content)::bigint) as size FROM " +
5717310a0c6a create database view for diagnostic purposes;
wenzelm
parents: 78266
diff changeset
    76
          Slices.table.ident,
5717310a0c6a create database view for diagnostic purposes;
wenzelm
parents: 78266
diff changeset
    77
        name = "slices_size")
5717310a0c6a create database view for diagnostic purposes;
wenzelm
parents: 78266
diff changeset
    78
    }
5717310a0c6a create database view for diagnostic purposes;
wenzelm
parents: 78266
diff changeset
    79
78196
140a6f2e3728 restore heaps from database, which takes precedence over file-system;
wenzelm
parents: 78193
diff changeset
    80
    def get_entry(db: SQL.Database, name: String): Option[SHA1.Digest] =
78183
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    81
      db.execute_query_statementO[String](
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    82
        Base.table.select(List(Base.digest), sql = Generic.name.where_equal(name)),
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    83
        _.string(Base.digest)
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    84
      ).flatMap(proper_string).map(SHA1.fake_digest)
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    85
78196
140a6f2e3728 restore heaps from database, which takes precedence over file-system;
wenzelm
parents: 78193
diff changeset
    86
    def read_entry(db: SQL.Database, name: String): List[Bytes] =
140a6f2e3728 restore heaps from database, which takes precedence over file-system;
wenzelm
parents: 78193
diff changeset
    87
      db.execute_query_statement(
140a6f2e3728 restore heaps from database, which takes precedence over file-system;
wenzelm
parents: 78193
diff changeset
    88
        Slices.table.select(List(Slices.content),
140a6f2e3728 restore heaps from database, which takes precedence over file-system;
wenzelm
parents: 78193
diff changeset
    89
          sql = Generic.name.where_equal(name) + SQL.order_by(List(Slices.slice))),
140a6f2e3728 restore heaps from database, which takes precedence over file-system;
wenzelm
parents: 78193
diff changeset
    90
        List.from[Bytes], _.bytes(Slices.content))
140a6f2e3728 restore heaps from database, which takes precedence over file-system;
wenzelm
parents: 78193
diff changeset
    91
78183
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    92
    def clean_entry(db: SQL.Database, name: String): Unit = {
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    93
      for (table <- List(Base.table, Slices.table)) {
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    94
        db.execute_statement(table.delete(sql = Base.name.where_equal(name)))
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    95
      }
78278
5717310a0c6a create database view for diagnostic purposes;
wenzelm
parents: 78266
diff changeset
    96
      db.create_view(Slices_Size.table)
78183
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    97
    }
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    98
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    99
    def prepare_entry(db: SQL.Database, name: String): Unit =
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   100
      db.execute_statement(Base.table.insert(), body =
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   101
        { stmt =>
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   102
          stmt.string(1) = name
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   103
          stmt.long(2) = None
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   104
          stmt.string(3) = None
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   105
        })
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   106
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   107
    def write_entry(db: SQL.Database, name: String, slice: Int, content: Bytes): Unit =
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   108
      db.execute_statement(Slices.table.insert(), body =
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   109
      { stmt =>
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   110
        stmt.string(1) = name
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   111
        stmt.int(2) = slice
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   112
        stmt.bytes(3) = content
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   113
      })
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   114
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   115
    def finish_entry(db: SQL.Database, name: String, size: Long, digest: SHA1.Digest): Unit =
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   116
      db.execute_statement(
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   117
        Base.table.update(List(Base.size, Base.digest), sql = Base.name.where_equal(name)),
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   118
        body =
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   119
          { stmt =>
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   120
            stmt.long(1) = size
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   121
            stmt.string(2) = digest.toString
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   122
          })
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   123
  }
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   124
78204
0aa5360fa88b clarified signature;
wenzelm
parents: 78197
diff changeset
   125
  def clean_entry(db: SQL.Database, session_name: String): Unit =
78396
7853d9072d1b renamed object Data to private_data, to emphasize its intended scope (but it is publicly accessible in the database);
wenzelm
parents: 78369
diff changeset
   126
    private_data.transaction_lock(db, create = true, label = "ML_Heap.clean_entry") {
7853d9072d1b renamed object Data to private_data, to emphasize its intended scope (but it is publicly accessible in the database);
wenzelm
parents: 78369
diff changeset
   127
      private_data.clean_entry(db, session_name)
78213
fd0430a7b7a4 avoid repeated open_database_server: synchronized transaction_lock;
wenzelm
parents: 78204
diff changeset
   128
    }
78186
721c118f7001 proper ML_Heap.clean_entry;
wenzelm
parents: 78183
diff changeset
   129
78204
0aa5360fa88b clarified signature;
wenzelm
parents: 78197
diff changeset
   130
  def get_entry(db: SQL.Database, session_name: String): Option[SHA1.Digest] =
78396
7853d9072d1b renamed object Data to private_data, to emphasize its intended scope (but it is publicly accessible in the database);
wenzelm
parents: 78369
diff changeset
   131
    private_data.transaction_lock(db, create = true, label = "ML_Heap.get_entry") {
7853d9072d1b renamed object Data to private_data, to emphasize its intended scope (but it is publicly accessible in the database);
wenzelm
parents: 78369
diff changeset
   132
      private_data.get_entry(db, session_name)
78213
fd0430a7b7a4 avoid repeated open_database_server: synchronized transaction_lock;
wenzelm
parents: 78204
diff changeset
   133
    }
78196
140a6f2e3728 restore heaps from database, which takes precedence over file-system;
wenzelm
parents: 78193
diff changeset
   134
78191
6e52cda26ad4 tuned signature;
wenzelm
parents: 78188
diff changeset
   135
  def store(
78183
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   136
    database: Option[SQL.Database],
78204
0aa5360fa88b clarified signature;
wenzelm
parents: 78197
diff changeset
   137
    session_name: String,
78183
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   138
    heap: Path,
78188
fd68b98de1f6 prefer system option;
wenzelm
parents: 78187
diff changeset
   139
    slice: Long,
78193
wenzelm
parents: 78191
diff changeset
   140
    cache: Compress.Cache = Compress.Cache.none
78183
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   141
  ): SHA1.Digest = {
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   142
    val digest = write_file_digest(heap)
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   143
    database match {
78204
0aa5360fa88b clarified signature;
wenzelm
parents: 78197
diff changeset
   144
      case None =>
78183
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   145
      case Some(db) =>
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   146
        val size = File.space(heap).bytes - sha1_prefix.length - SHA1.digest_length
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   147
78188
fd68b98de1f6 prefer system option;
wenzelm
parents: 78187
diff changeset
   148
        val slices = (size.toDouble / slice.toDouble).ceil.toInt
78183
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   149
        val step = (size.toDouble / slices.toDouble).ceil.toLong
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   150
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   151
        try {
78396
7853d9072d1b renamed object Data to private_data, to emphasize its intended scope (but it is publicly accessible in the database);
wenzelm
parents: 78369
diff changeset
   152
          private_data.transaction_lock(db, create = true, label = "ML_Heap.store1") {
7853d9072d1b renamed object Data to private_data, to emphasize its intended scope (but it is publicly accessible in the database);
wenzelm
parents: 78369
diff changeset
   153
            private_data.prepare_entry(db, session_name)
78213
fd0430a7b7a4 avoid repeated open_database_server: synchronized transaction_lock;
wenzelm
parents: 78204
diff changeset
   154
          }
78183
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   155
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   156
          for (i <- 0 until slices) {
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   157
            val j = i + 1
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   158
            val offset = step * i
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   159
            val limit = if (j < slices) step * j else size
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   160
            val content =
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   161
              Bytes.read_file(heap.file, offset = offset, limit = limit)
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   162
                .compress(cache = cache)
78396
7853d9072d1b renamed object Data to private_data, to emphasize its intended scope (but it is publicly accessible in the database);
wenzelm
parents: 78369
diff changeset
   163
            private_data.transaction_lock(db, label = "ML_Heap.store2") {
7853d9072d1b renamed object Data to private_data, to emphasize its intended scope (but it is publicly accessible in the database);
wenzelm
parents: 78369
diff changeset
   164
              private_data.write_entry(db, session_name, i, content)
78213
fd0430a7b7a4 avoid repeated open_database_server: synchronized transaction_lock;
wenzelm
parents: 78204
diff changeset
   165
            }
78183
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   166
          }
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   167
78396
7853d9072d1b renamed object Data to private_data, to emphasize its intended scope (but it is publicly accessible in the database);
wenzelm
parents: 78369
diff changeset
   168
          private_data.transaction_lock(db, label = "ML_Heap.store3") {
7853d9072d1b renamed object Data to private_data, to emphasize its intended scope (but it is publicly accessible in the database);
wenzelm
parents: 78369
diff changeset
   169
            private_data.finish_entry(db, session_name, size, digest)
78213
fd0430a7b7a4 avoid repeated open_database_server: synchronized transaction_lock;
wenzelm
parents: 78204
diff changeset
   170
          }
78183
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   171
        }
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   172
        catch { case exn: Throwable =>
78396
7853d9072d1b renamed object Data to private_data, to emphasize its intended scope (but it is publicly accessible in the database);
wenzelm
parents: 78369
diff changeset
   173
          private_data.transaction_lock(db, create = true, label = "ML_Heap.store4") {
7853d9072d1b renamed object Data to private_data, to emphasize its intended scope (but it is publicly accessible in the database);
wenzelm
parents: 78369
diff changeset
   174
            private_data.clean_entry(db, session_name)
78213
fd0430a7b7a4 avoid repeated open_database_server: synchronized transaction_lock;
wenzelm
parents: 78204
diff changeset
   175
          }
78183
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   176
          throw exn
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   177
        }
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   178
    }
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   179
    digest
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   180
  }
78196
140a6f2e3728 restore heaps from database, which takes precedence over file-system;
wenzelm
parents: 78193
diff changeset
   181
140a6f2e3728 restore heaps from database, which takes precedence over file-system;
wenzelm
parents: 78193
diff changeset
   182
  def restore(
78204
0aa5360fa88b clarified signature;
wenzelm
parents: 78197
diff changeset
   183
    database: Option[SQL.Database],
0aa5360fa88b clarified signature;
wenzelm
parents: 78197
diff changeset
   184
    session_name: String,
78196
140a6f2e3728 restore heaps from database, which takes precedence over file-system;
wenzelm
parents: 78193
diff changeset
   185
    heap: Path,
140a6f2e3728 restore heaps from database, which takes precedence over file-system;
wenzelm
parents: 78193
diff changeset
   186
    cache: Compress.Cache = Compress.Cache.none
140a6f2e3728 restore heaps from database, which takes precedence over file-system;
wenzelm
parents: 78193
diff changeset
   187
  ): Unit = {
78204
0aa5360fa88b clarified signature;
wenzelm
parents: 78197
diff changeset
   188
    database match {
0aa5360fa88b clarified signature;
wenzelm
parents: 78197
diff changeset
   189
      case None =>
0aa5360fa88b clarified signature;
wenzelm
parents: 78197
diff changeset
   190
      case Some(db) =>
78396
7853d9072d1b renamed object Data to private_data, to emphasize its intended scope (but it is publicly accessible in the database);
wenzelm
parents: 78369
diff changeset
   191
        private_data.transaction_lock(db, create = true, label = "ML_Heap.restore") {
7853d9072d1b renamed object Data to private_data, to emphasize its intended scope (but it is publicly accessible in the database);
wenzelm
parents: 78369
diff changeset
   192
          val db_digest = private_data.get_entry(db, session_name)
78204
0aa5360fa88b clarified signature;
wenzelm
parents: 78197
diff changeset
   193
          val file_digest = read_file_digest(heap)
78196
140a6f2e3728 restore heaps from database, which takes precedence over file-system;
wenzelm
parents: 78193
diff changeset
   194
78204
0aa5360fa88b clarified signature;
wenzelm
parents: 78197
diff changeset
   195
          if (db_digest.isDefined && db_digest != file_digest) {
78509
146468e05dd4 more robust: atomic file-system result via tmp file;
wenzelm
parents: 78396
diff changeset
   196
            val base_dir = Isabelle_System.make_directory(heap.expand.dir)
146468e05dd4 more robust: atomic file-system result via tmp file;
wenzelm
parents: 78396
diff changeset
   197
            Isabelle_System.with_tmp_file(session_name + "_", base_dir = base_dir.file) { tmp =>
146468e05dd4 more robust: atomic file-system result via tmp file;
wenzelm
parents: 78396
diff changeset
   198
              Bytes.write(tmp, Bytes.empty)
78396
7853d9072d1b renamed object Data to private_data, to emphasize its intended scope (but it is publicly accessible in the database);
wenzelm
parents: 78369
diff changeset
   199
              for (slice <- private_data.read_entry(db, session_name)) {
78509
146468e05dd4 more robust: atomic file-system result via tmp file;
wenzelm
parents: 78396
diff changeset
   200
                Bytes.append(tmp, slice.uncompress(cache = cache))
78204
0aa5360fa88b clarified signature;
wenzelm
parents: 78197
diff changeset
   201
              }
78509
146468e05dd4 more robust: atomic file-system result via tmp file;
wenzelm
parents: 78396
diff changeset
   202
              val digest = write_file_digest(tmp)
146468e05dd4 more robust: atomic file-system result via tmp file;
wenzelm
parents: 78396
diff changeset
   203
              if (db_digest.get == digest) {
146468e05dd4 more robust: atomic file-system result via tmp file;
wenzelm
parents: 78396
diff changeset
   204
                Isabelle_System.chmod("a+r", tmp)
146468e05dd4 more robust: atomic file-system result via tmp file;
wenzelm
parents: 78396
diff changeset
   205
                Isabelle_System.move_file(tmp, heap)
146468e05dd4 more robust: atomic file-system result via tmp file;
wenzelm
parents: 78396
diff changeset
   206
              }
146468e05dd4 more robust: atomic file-system result via tmp file;
wenzelm
parents: 78396
diff changeset
   207
              else error("Incoherent content for session heap " + quote(session_name))
146468e05dd4 more robust: atomic file-system result via tmp file;
wenzelm
parents: 78396
diff changeset
   208
            }
78196
140a6f2e3728 restore heaps from database, which takes precedence over file-system;
wenzelm
parents: 78193
diff changeset
   209
          }
78204
0aa5360fa88b clarified signature;
wenzelm
parents: 78197
diff changeset
   210
        }
78196
140a6f2e3728 restore heaps from database, which takes precedence over file-system;
wenzelm
parents: 78193
diff changeset
   211
    }
140a6f2e3728 restore heaps from database, which takes precedence over file-system;
wenzelm
parents: 78193
diff changeset
   212
  }
76991
6a078c80eab6 clarified modules;
wenzelm
parents:
diff changeset
   213
}