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) |