src/Pure/ML/ml_heap.scala
changeset 79677 49370f0f7911
parent 78958 c125f75a5144
child 79678 5979ba127524
equal deleted inserted replaced
79676:0cac7e3634d0 79677:49370f0f7911
    75         body = "SELECT name, slice, pg_size_pretty(length(content)::bigint) as size FROM " +
    75         body = "SELECT name, slice, pg_size_pretty(length(content)::bigint) as size FROM " +
    76           Slices.table.ident,
    76           Slices.table.ident,
    77         name = "slices_size")
    77         name = "slices_size")
    78     }
    78     }
    79 
    79 
    80     def get_entries(db: SQL.Database, names: Iterable[String]): Map[String, SHA1.Digest] = {
    80     def read_digests(db: SQL.Database, names: Iterable[String]): Map[String, SHA1.Digest] = {
    81       require(names.nonEmpty)
    81       require(names.nonEmpty)
    82 
    82 
    83       db.execute_query_statement(
    83       db.execute_query_statement(
    84         Base.table.select(List(Base.name, Base.digest),
    84         Base.table.select(List(Base.name, Base.digest),
    85           sql = Generic.name.where_member(names)),
    85           sql = Generic.name.where_member(names)),
    89         case (_, "") => None
    89         case (_, "") => None
    90         case (name, digest) => Some(name -> SHA1.fake_digest(digest))
    90         case (name, digest) => Some(name -> SHA1.fake_digest(digest))
    91       }).toMap
    91       }).toMap
    92     }
    92     }
    93 
    93 
    94     def read_entry(db: SQL.Database, name: String): List[Bytes] =
    94     def read_slices(db: SQL.Database, name: String): List[Bytes] =
    95       db.execute_query_statement(
    95       db.execute_query_statement(
    96         Slices.table.select(List(Slices.content),
    96         Slices.table.select(List(Slices.content),
    97           sql = Generic.name.where_equal(name) + SQL.order_by(List(Slices.slice))),
    97           sql = Generic.name.where_equal(name) + SQL.order_by(List(Slices.slice))),
    98         List.from[Bytes], _.bytes(Slices.content))
    98         List.from[Bytes], _.bytes(Slices.content))
    99 
    99 
   110           stmt.string(1) = name
   110           stmt.string(1) = name
   111           stmt.long(2) = None
   111           stmt.long(2) = None
   112           stmt.string(3) = None
   112           stmt.string(3) = None
   113         })
   113         })
   114 
   114 
   115     def write_entry(db: SQL.Database, name: String, slice: Int, content: Bytes): Unit =
   115     def write_slice(db: SQL.Database, name: String, slice: Int, content: Bytes): Unit =
   116       db.execute_statement(Slices.table.insert(), body =
   116       db.execute_statement(Slices.table.insert(), body =
   117       { stmt =>
   117       { stmt =>
   118         stmt.string(1) = name
   118         stmt.string(1) = name
   119         stmt.int(2) = slice
   119         stmt.int(2) = slice
   120         stmt.bytes(3) = content
   120         stmt.bytes(3) = content
   133   def clean_entry(db: SQL.Database, session_name: String): Unit =
   133   def clean_entry(db: SQL.Database, session_name: String): Unit =
   134     private_data.transaction_lock(db, create = true, label = "ML_Heap.clean_entry") {
   134     private_data.transaction_lock(db, create = true, label = "ML_Heap.clean_entry") {
   135       private_data.clean_entry(db, session_name)
   135       private_data.clean_entry(db, session_name)
   136     }
   136     }
   137 
   137 
   138   def get_entries(db: SQL.Database, names: Iterable[String]): Map[String, SHA1.Digest] =
   138   def read_digests(db: SQL.Database, names: Iterable[String]): Map[String, SHA1.Digest] =
   139     private_data.transaction_lock(db, create = true, label = "ML_Heap.get_entries") {
   139     private_data.transaction_lock(db, create = true, label = "ML_Heap.read_digests") {
   140       private_data.get_entries(db, names)
   140       private_data.read_digests(db, names)
   141     }
   141     }
   142 
   142 
   143   def store(
   143   def store(
   144     database: Option[SQL.Database],
   144     database: Option[SQL.Database],
   145     session_name: String,
   145     session_name: String,
   167             val limit = if (j < slices) step * j else size
   167             val limit = if (j < slices) step * j else size
   168             val content =
   168             val content =
   169               Bytes.read_file(heap, offset = offset, limit = limit)
   169               Bytes.read_file(heap, offset = offset, limit = limit)
   170                 .compress(cache = cache)
   170                 .compress(cache = cache)
   171             private_data.transaction_lock(db, label = "ML_Heap.store2") {
   171             private_data.transaction_lock(db, label = "ML_Heap.store2") {
   172               private_data.write_entry(db, session_name, i, content)
   172               private_data.write_slice(db, session_name, i, content)
   173             }
   173             }
   174           }
   174           }
   175 
   175 
   176           private_data.transaction_lock(db, label = "ML_Heap.store3") {
   176           private_data.transaction_lock(db, label = "ML_Heap.store3") {
   177             private_data.finish_entry(db, session_name, size, digest)
   177             private_data.finish_entry(db, session_name, size, digest)
   193     cache: Compress.Cache = Compress.Cache.none
   193     cache: Compress.Cache = Compress.Cache.none
   194   ): Unit = {
   194   ): Unit = {
   195     database match {
   195     database match {
   196       case Some(db) if heaps.nonEmpty =>
   196       case Some(db) if heaps.nonEmpty =>
   197         private_data.transaction_lock(db, create = true, label = "ML_Heap.restore") {
   197         private_data.transaction_lock(db, create = true, label = "ML_Heap.restore") {
   198           val db_digests = private_data.get_entries(db, heaps.map(_.file_name))
   198           val db_digests = private_data.read_digests(db, heaps.map(_.file_name))
   199           for (heap <- heaps) {
   199           for (heap <- heaps) {
   200             val session_name = heap.file_name
   200             val session_name = heap.file_name
   201             val file_digest = read_file_digest(heap)
   201             val file_digest = read_file_digest(heap)
   202             val db_digest = db_digests.get(session_name)
   202             val db_digest = db_digests.get(session_name)
   203             if (db_digest.isDefined && db_digest != file_digest) {
   203             if (db_digest.isDefined && db_digest != file_digest) {
   204               val base_dir = Isabelle_System.make_directory(heap.expand.dir)
   204               val base_dir = Isabelle_System.make_directory(heap.expand.dir)
   205               Isabelle_System.with_tmp_file(session_name + "_", base_dir = base_dir.file) { tmp =>
   205               Isabelle_System.with_tmp_file(session_name + "_", base_dir = base_dir.file) { tmp =>
   206                 Bytes.write(tmp, Bytes.empty)
   206                 Bytes.write(tmp, Bytes.empty)
   207                 for (slice <- private_data.read_entry(db, session_name)) {
   207                 for (slice <- private_data.read_slices(db, session_name)) {
   208                   Bytes.append(tmp, slice.uncompress(cache = cache))
   208                   Bytes.append(tmp, slice.uncompress(cache = cache))
   209                 }
   209                 }
   210                 val digest = write_file_digest(tmp)
   210                 val digest = write_file_digest(tmp)
   211                 if (db_digest.get == digest) {
   211                 if (db_digest.get == digest) {
   212                   Isabelle_System.chmod("a+r", tmp)
   212                   Isabelle_System.chmod("a+r", tmp)