more thorough ML_Heap.restore: include ancestors; prefer simultaneous ML_Heap.get_entries: just one database access for heap hierarchy;
--- a/src/Pure/ML/ml_heap.scala Thu Aug 10 19:58:23 2023 +0200
+++ b/src/Pure/ML/ml_heap.scala Thu Aug 10 20:30:37 2023 +0200
@@ -77,11 +77,19 @@
name = "slices_size")
}
- def get_entry(db: SQL.Database, name: String): Option[SHA1.Digest] =
- db.execute_query_statementO[String](
- Base.table.select(List(Base.digest), sql = Generic.name.where_equal(name)),
- _.string(Base.digest)
- ).flatMap(proper_string).map(SHA1.fake_digest)
+ def get_entries(db: SQL.Database, names: Iterable[String]): Map[String, SHA1.Digest] = {
+ require(names.nonEmpty)
+
+ db.execute_query_statement(
+ Base.table.select(List(Base.name, Base.digest),
+ sql = Generic.name.where_member(names)),
+ List.from[(String, String)],
+ res => res.string(Base.name) -> res.string(Base.digest)
+ ).flatMap({
+ case (_, "") => None
+ case (name, digest) => Some(name -> SHA1.fake_digest(digest))
+ }).toMap
+ }
def read_entry(db: SQL.Database, name: String): List[Bytes] =
db.execute_query_statement(
@@ -127,9 +135,9 @@
private_data.clean_entry(db, session_name)
}
- def get_entry(db: SQL.Database, session_name: String): Option[SHA1.Digest] =
- private_data.transaction_lock(db, create = true, label = "ML_Heap.get_entry") {
- private_data.get_entry(db, session_name)
+ def get_entries(db: SQL.Database, names: Iterable[String]): Map[String, SHA1.Digest] =
+ private_data.transaction_lock(db, create = true, label = "ML_Heap.get_entries") {
+ private_data.get_entries(db, names)
}
def store(
@@ -181,33 +189,35 @@
def restore(
database: Option[SQL.Database],
- session_name: String,
- heap: Path,
+ heaps: List[Path],
cache: Compress.Cache = Compress.Cache.none
): Unit = {
database match {
- case None =>
- case Some(db) =>
+ case Some(db) if heaps.nonEmpty =>
private_data.transaction_lock(db, create = true, label = "ML_Heap.restore") {
- val db_digest = private_data.get_entry(db, session_name)
- val file_digest = read_file_digest(heap)
-
- if (db_digest.isDefined && db_digest != file_digest) {
- val base_dir = Isabelle_System.make_directory(heap.expand.dir)
- Isabelle_System.with_tmp_file(session_name + "_", base_dir = base_dir.file) { tmp =>
- Bytes.write(tmp, Bytes.empty)
- for (slice <- private_data.read_entry(db, session_name)) {
- Bytes.append(tmp, slice.uncompress(cache = cache))
+ val db_digests = private_data.get_entries(db, heaps.map(_.file_name))
+ for (heap <- heaps) {
+ val session_name = heap.file_name
+ val file_digest = read_file_digest(heap)
+ val db_digest = db_digests.get(session_name)
+ if (db_digest.isDefined && db_digest != file_digest) {
+ val base_dir = Isabelle_System.make_directory(heap.expand.dir)
+ Isabelle_System.with_tmp_file(session_name + "_", base_dir = base_dir.file) { tmp =>
+ Bytes.write(tmp, Bytes.empty)
+ for (slice <- private_data.read_entry(db, session_name)) {
+ Bytes.append(tmp, slice.uncompress(cache = cache))
+ }
+ val digest = write_file_digest(tmp)
+ if (db_digest.get == digest) {
+ Isabelle_System.chmod("a+r", tmp)
+ Isabelle_System.move_file(tmp, heap)
+ }
+ else error("Incoherent content for session heap " + quote(session_name))
}
- val digest = write_file_digest(tmp)
- if (db_digest.get == digest) {
- Isabelle_System.chmod("a+r", tmp)
- Isabelle_System.move_file(tmp, heap)
- }
- else error("Incoherent content for session heap " + quote(session_name))
}
}
}
+ case _ =>
}
}
}
--- a/src/Pure/Thy/store.scala Thu Aug 10 19:58:23 2023 +0200
+++ b/src/Pure/Thy/store.scala Thu Aug 10 20:30:37 2023 +0200
@@ -271,8 +271,15 @@
cat_lines(input_dirs.map(dir => " " + File.standard_path(dir))))
def heap_shasum(database_server: Option[SQL.Database], name: String): SHA1.Shasum = {
- def get_database = database_server.flatMap(ML_Heap.get_entry(_, name))
- def get_file = find_heap(name).flatMap(ML_Heap.read_file_digest)
+ def get_database: Option[SHA1.Digest] = {
+ for {
+ db <- database_server
+ digest <- ML_Heap.get_entries(db, List(name)).valuesIterator.nextOption()
+ } yield digest
+ }
+
+ def get_file: Option[SHA1.Digest] =
+ find_heap(name).flatMap(ML_Heap.read_file_digest)
get_database orElse get_file match {
case Some(digest) => SHA1.shasum(digest, name)
--- a/src/Pure/Tools/build_process.scala Thu Aug 10 19:58:23 2023 +0200
+++ b/src/Pure/Tools/build_process.scala Thu Aug 10 20:30:37 2023 +0200
@@ -995,8 +995,8 @@
val cancelled = progress.stopped || !ancestor_results.forall(_.ok)
if (!skipped && !cancelled) {
- ML_Heap.restore(_database_server, session_name, store.output_heap(session_name),
- cache = store.cache.compress)
+ val heaps = (session_name :: ancestor_results.map(_.name)).map(store.output_heap)
+ ML_Heap.restore(_database_server, heaps, cache = store.cache.compress)
}
val result_name = (session_name, worker_uuid, build_uuid)