src/Pure/ML/ml_heap.scala
author wenzelm
Wed, 21 Jun 2023 11:42:11 +0200
changeset 78186 721c118f7001
parent 78183 8d57ed9e27a7
child 78187 2df0f3604a67
permissions -rw-r--r--
proper ML_Heap.clean_entry;
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
78183
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    46
  object Data {
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    47
    def make_table(name: String, columns: List[SQL.Column], body: String = ""): SQL.Table =
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    48
      SQL.Table("isabelle_heaps" + if_proper(name, "_" + name), columns, body = body)
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    49
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    50
    object Generic {
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    51
      val name = SQL.Column.string("name").make_primary_key
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    52
    }
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    53
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    54
    object Base {
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    55
      val name = Generic.name
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    56
      val size = SQL.Column.long("size")
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    57
      val digest = SQL.Column.string("digest")
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    58
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    59
      val table = make_table("", List(name, size, digest))
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    60
    }
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    61
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    62
    object Slices {
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    63
      val name = Generic.name
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    64
      val slice = SQL.Column.int("slice").make_primary_key
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    65
      val content = SQL.Column.bytes("content")
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    66
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    67
      val table = make_table("slices", List(name, slice, content))
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    68
    }
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    69
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    70
    def known_entry(db: SQL.Database, name: String): Boolean =
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    71
      db.execute_query_statementB(
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    72
        Base.table.select(List(Base.name), sql = Base.name.where_equal(name)))
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    73
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    74
    def defined_entry(db: SQL.Database, name: String): Option[SHA1.Digest] =
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    75
      db.execute_query_statementO[String](
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    76
        Base.table.select(List(Base.digest), sql = Generic.name.where_equal(name)),
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    77
        _.string(Base.digest)
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    78
      ).flatMap(proper_string).map(SHA1.fake_digest)
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    79
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    80
    def clean_entry(db: SQL.Database, name: String): Unit = {
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    81
      for (table <- List(Base.table, Slices.table)) {
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    82
        db.execute_statement(table.delete(sql = Base.name.where_equal(name)))
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    83
      }
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    84
    }
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    85
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    86
    def prepare_entry(db: SQL.Database, name: String): Unit =
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    87
      db.execute_statement(Base.table.insert(), body =
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    88
        { stmt =>
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    89
          stmt.string(1) = name
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    90
          stmt.long(2) = None
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    91
          stmt.string(3) = None
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    92
        })
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    93
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    94
    def write_entry(db: SQL.Database, name: String, slice: Int, content: Bytes): Unit =
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    95
      db.execute_statement(Slices.table.insert(), body =
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    96
      { stmt =>
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    97
        stmt.string(1) = name
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    98
        stmt.int(2) = slice
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
    99
        stmt.bytes(3) = content
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   100
      })
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   101
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   102
    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
   103
      db.execute_statement(
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   104
        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
   105
        body =
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   106
          { stmt =>
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   107
            stmt.long(1) = size
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   108
            stmt.string(2) = digest.toString
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   109
          })
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   110
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   111
    val all_tables: SQL.Tables = SQL.Tables(Base.table, Slices.table)
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   112
  }
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   113
78186
721c118f7001 proper ML_Heap.clean_entry;
wenzelm
parents: 78183
diff changeset
   114
  def clean_entry(db: SQL.Database, name: String): Unit =
721c118f7001 proper ML_Heap.clean_entry;
wenzelm
parents: 78183
diff changeset
   115
    db.transaction_lock(Data.all_tables, create = true) { Data.clean_entry(db, name) }
721c118f7001 proper ML_Heap.clean_entry;
wenzelm
parents: 78183
diff changeset
   116
78183
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   117
  def write_digest(
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   118
    database: Option[SQL.Database],
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   119
    heap: Path,
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   120
    cache: Compress.Cache = Compress.Cache.none,
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   121
    slice_size: Long = Space.MiB(50).bytes
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   122
  ): SHA1.Digest = {
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   123
    val digest = write_file_digest(heap)
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   124
    database match {
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   125
      case Some(db) =>
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   126
        val name = heap.file_name
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   127
        val size = File.space(heap).bytes - sha1_prefix.length - SHA1.digest_length
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   128
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   129
        val slices = (size.toDouble / slice_size.toDouble).ceil.toInt
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   130
        val step = (size.toDouble / slices.toDouble).ceil.toLong
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   131
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   132
        try {
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   133
          db.transaction_lock(Data.all_tables, create = true) { Data.prepare_entry(db, name) }
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   134
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   135
          for (i <- 0 until slices) {
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   136
            val j = i + 1
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   137
            val offset = step * i
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   138
            val limit = if (j < slices) step * j else size
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   139
            val content =
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   140
              Bytes.read_file(heap.file, offset = offset, limit = limit)
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   141
                .compress(cache = cache)
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   142
            db.transaction_lock(Data.all_tables) { Data.write_entry(db, name, i, content) }
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   143
          }
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   144
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   145
          db.transaction_lock(Data.all_tables) { Data.finish_entry(db, name, size, digest) }
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   146
        }
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   147
        catch { case exn: Throwable =>
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   148
          db.transaction_lock(Data.all_tables, create = true) { Data.clean_entry(db, name) }
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   149
          throw exn
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   150
        }
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   151
      case None =>
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   152
    }
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   153
    digest
8d57ed9e27a7 store heaps within database server;
wenzelm
parents: 78182
diff changeset
   154
  }
76991
6a078c80eab6 clarified modules;
wenzelm
parents:
diff changeset
   155
}