76 (nodes.iterator ++ nodes_committed.iterator).forall({ case (_, st) => st.ok }) |
78 (nodes.iterator ++ nodes_committed.iterator).forall({ case (_, st) => st.ok }) |
77 } |
79 } |
78 |
80 |
79 val default_check_delay: Double = 0.5 |
81 val default_check_delay: Double = 0.5 |
80 val default_nodes_status_delay: Double = -1.0 |
82 val default_nodes_status_delay: Double = -1.0 |
|
83 val default_commit_clean_delay: Double = 60.0 |
81 |
84 |
82 |
85 |
83 class Session private[Thy_Resources]( |
86 class Session private[Thy_Resources]( |
84 session_name: String, |
87 session_name: String, |
85 session_options: Options, |
88 session_options: Options, |
133 } yield name |
136 } yield name |
134 (initialized, copy(already_initialized = already_initialized ++ initialized)) |
137 (initialized, copy(already_initialized = already_initialized ++ initialized)) |
135 } |
138 } |
136 |
139 |
137 def cancel_result { result.cancel } |
140 def cancel_result { result.cancel } |
|
141 def finished_result: Boolean = result.is_finished |
138 def await_result { result.join_result } |
142 def await_result { result.join_result } |
139 def join_result: Theories_Result = result.join |
143 def join_result: Theories_Result = result.join |
140 def check_result( |
144 def check_result( |
141 state: Document.State, |
145 state: Document.State, |
142 version: Document.Version, |
146 version: Document.Version, |
195 watchdog_timeout: Time = Time.zero, |
199 watchdog_timeout: Time = Time.zero, |
196 nodes_status_delay: Time = Time.seconds(default_nodes_status_delay), |
200 nodes_status_delay: Time = Time.seconds(default_nodes_status_delay), |
197 id: UUID = UUID(), |
201 id: UUID = UUID(), |
198 // commit: must not block, must not fail |
202 // commit: must not block, must not fail |
199 commit: Option[(Document.Snapshot, Document_Status.Node_Status) => Unit] = None, |
203 commit: Option[(Document.Snapshot, Document_Status.Node_Status) => Unit] = None, |
|
204 commit_clean_delay: Time = Time.seconds(default_commit_clean_delay), |
200 progress: Progress = No_Progress): Theories_Result = |
205 progress: Progress = No_Progress): Theories_Result = |
201 { |
206 { |
202 val dep_theories = |
207 val dep_theories = |
203 { |
208 { |
204 val import_names = |
209 val import_names = |
239 val delay_nodes_status = |
244 val delay_nodes_status = |
240 Standard_Thread.delay_first(nodes_status_delay max Time.zero) { |
245 Standard_Thread.delay_first(nodes_status_delay max Time.zero) { |
241 progress.nodes_status(use_theories_state.value.nodes_status) |
246 progress.nodes_status(use_theories_state.value.nodes_status) |
242 } |
247 } |
243 |
248 |
|
249 val delay_commit_clean = |
|
250 Standard_Thread.delay_first(commit_clean_delay max Time.zero) { |
|
251 val clean = use_theories_state.value.already_committed.keySet |
|
252 resources.clean_theories(session, id, clean) |
|
253 } |
|
254 |
244 Session.Consumer[Session.Commands_Changed](getClass.getName) { |
255 Session.Consumer[Session.Commands_Changed](getClass.getName) { |
245 case changed => |
256 case changed => |
246 if (changed.nodes.exists(dep_theories_set)) { |
257 if (changed.nodes.exists(dep_theories_set)) { |
247 val snapshot = session.snapshot() |
258 val snapshot = session.snapshot() |
248 val state = snapshot.state |
259 val state = snapshot.state |
289 |
300 |
290 for ((theory, percentage) <- theory_percentages) |
301 for ((theory, percentage) <- theory_percentages) |
291 progress.theory_percentage("", theory, percentage) |
302 progress.theory_percentage("", theory, percentage) |
292 |
303 |
293 check_result() |
304 check_result() |
|
305 |
|
306 if (commit.isDefined && commit_clean_delay >= Time.zero) { |
|
307 if (use_theories_state.value.finished_result) |
|
308 delay_commit_clean.revoke |
|
309 else delay_commit_clean.invoke |
|
310 } |
294 } |
311 } |
295 } |
312 } |
296 } |
313 } |
297 |
314 |
298 try { |
315 try { |
361 |
378 |
362 sealed case class State( |
379 sealed case class State( |
363 required: Multi_Map[Document.Node.Name, UUID] = Multi_Map.empty, |
380 required: Multi_Map[Document.Node.Name, UUID] = Multi_Map.empty, |
364 theories: Map[Document.Node.Name, Theory] = Map.empty) |
381 theories: Map[Document.Node.Name, Theory] = Map.empty) |
365 { |
382 { |
|
383 lazy val theory_graph: Graph[Document.Node.Name, Unit] = |
|
384 { |
|
385 val entries = |
|
386 for ((name, theory) <- theories.toList) |
|
387 yield ((name, ()), theory.node_header.imports.map(_._1).filter(theories.isDefinedAt(_))) |
|
388 Graph.make(entries, symmetric = true)(Document.Node.Name.Ordering) |
|
389 } |
|
390 |
366 def is_required(name: Document.Node.Name): Boolean = required.isDefinedAt(name) |
391 def is_required(name: Document.Node.Name): Boolean = required.isDefinedAt(name) |
367 |
392 |
368 def insert_required(id: UUID, names: List[Document.Node.Name]): State = |
393 def insert_required(id: UUID, names: List[Document.Node.Name]): State = |
369 copy(required = (required /: names)(_.insert(_, id))) |
394 copy(required = (required /: names)(_.insert(_, id))) |
370 |
395 |
384 { |
409 { |
385 require(remove.forall(name => !is_required(name))) |
410 require(remove.forall(name => !is_required(name))) |
386 copy(theories = theories -- remove) |
411 copy(theories = theories -- remove) |
387 } |
412 } |
388 |
413 |
389 lazy val theory_graph: Graph[Document.Node.Name, Unit] = |
414 def unload_theories(session: Session, id: UUID, dep_theories: List[Document.Node.Name]): State = |
390 { |
415 { |
391 val entries = |
416 val st1 = remove_required(id, dep_theories) |
392 for ((name, theory) <- theories.toList) |
417 val theory_edits = |
393 yield ((name, ()), theory.node_header.imports.map(_._1).filter(theories.isDefinedAt(_))) |
418 for { |
394 Graph.make(entries, symmetric = true)(Document.Node.Name.Ordering) |
419 node_name <- dep_theories |
|
420 theory <- st1.theories.get(node_name) |
|
421 } |
|
422 yield { |
|
423 val theory1 = theory.required(st1.is_required(node_name)) |
|
424 val edits = theory1.node_edits(Some(theory)) |
|
425 (edits, (node_name, theory1)) |
|
426 } |
|
427 session.update(Document.Blobs.empty, theory_edits.flatMap(_._1)) |
|
428 st1.update_theories(theory_edits.map(_._2)) |
|
429 } |
|
430 |
|
431 def purge_theories(session: Session, nodes: List[Document.Node.Name]) |
|
432 : ((List[Document.Node.Name], List[Document.Node.Name]), State) = |
|
433 { |
|
434 val all_nodes = theory_graph.topological_order |
|
435 val purge = nodes.filterNot(is_required(_)).toSet |
|
436 |
|
437 val retain = theory_graph.all_preds(all_nodes.filterNot(purge)).toSet |
|
438 val (retained, purged) = all_nodes.partition(retain) |
|
439 |
|
440 val purge_edits = purged.flatMap(name => theories(name).purge_edits) |
|
441 session.update(Document.Blobs.empty, purge_edits) |
|
442 |
|
443 ((purged, retained), remove_theories(purged)) |
|
444 } |
|
445 |
|
446 def frontier_theories(clean: Set[Document.Node.Name]): Set[Document.Node.Name] = |
|
447 { |
|
448 @tailrec def frontier(base: List[Document.Node.Name], front: Set[Document.Node.Name]) |
|
449 : Set[Document.Node.Name] = |
|
450 { |
|
451 val add = base.filter(b => theory_graph.imm_succs(b).forall(front)) |
|
452 if (add.isEmpty) front |
|
453 else { |
|
454 val pre_add = add.map(theory_graph.imm_preds) |
|
455 val base1 = (pre_add.head /: pre_add.tail)(_ ++ _).toList.filter(clean) |
|
456 frontier(base1, front ++ add) |
|
457 } |
|
458 } |
|
459 frontier(theory_graph.maximals.filter(clean), Set.empty) |
395 } |
460 } |
396 } |
461 } |
397 } |
462 } |
398 |
463 |
399 class Thy_Resources(session_base: Sessions.Base, log: Logger = No_Logger) |
464 class Thy_Resources(session_base: Sessions.Base, log: Logger = No_Logger) |
436 session.update(Document.Blobs.empty, theory_edits.flatMap(_._1)) |
501 session.update(Document.Blobs.empty, theory_edits.flatMap(_._1)) |
437 st1.update_theories(theory_edits.map(_._2)) |
502 st1.update_theories(theory_edits.map(_._2)) |
438 }) |
503 }) |
439 } |
504 } |
440 |
505 |
441 def unload_theories(session: Session, id: UUID, dep_theories: List[Document.Node.Name]) |
506 def unload_theories( |
|
507 session: Thy_Resources.Session, id: UUID, dep_theories: List[Document.Node.Name]) |
|
508 { |
|
509 state.change(_.unload_theories(session, id, dep_theories)) |
|
510 } |
|
511 |
|
512 def clean_theories(session: Thy_Resources.Session, id: UUID, clean: Set[Document.Node.Name]) |
442 { |
513 { |
443 state.change(st => |
514 state.change(st => |
444 { |
515 { |
445 val st1 = st.remove_required(id, dep_theories) |
516 val frontier = st.frontier_theories(clean).toList |
446 val theory_edits = |
517 if (frontier.isEmpty) st |
447 for { |
518 else { |
448 node_name <- dep_theories |
519 val st1 = st.unload_theories(session, id, frontier) |
449 theory <- st1.theories.get(node_name) |
520 val (_, st2) = st1.purge_theories(session, frontier) |
450 } |
521 st2 |
451 yield { |
522 } |
452 val theory1 = theory.required(st1.is_required(node_name)) |
|
453 val edits = theory1.node_edits(Some(theory)) |
|
454 (edits, (node_name, theory1)) |
|
455 } |
|
456 session.update(Document.Blobs.empty, theory_edits.flatMap(_._1)) |
|
457 st1.update_theories(theory_edits.map(_._2)) |
|
458 }) |
523 }) |
459 } |
524 } |
460 |
525 |
461 def purge_theories(session: Session, nodes: Option[List[Document.Node.Name]]) |
526 def purge_theories(session: Thy_Resources.Session, nodes: Option[List[Document.Node.Name]]) |
462 : (List[Document.Node.Name], List[Document.Node.Name]) = |
527 : (List[Document.Node.Name], List[Document.Node.Name]) = |
463 { |
528 { |
464 state.change_result(st => |
529 state.change_result(st => st.purge_theories(session, nodes getOrElse st.theory_graph.keys)) |
465 { |
|
466 val graph = st.theory_graph |
|
467 val all_nodes = graph.topological_order |
|
468 |
|
469 val purge = |
|
470 (if (nodes.isEmpty) all_nodes else nodes.get.filter(graph.defined(_))). |
|
471 filterNot(st.is_required(_)).toSet |
|
472 |
|
473 val retain = graph.all_preds(all_nodes.filterNot(purge)).toSet |
|
474 val (retained, purged) = all_nodes.partition(retain) |
|
475 |
|
476 val purge_edits = purged.flatMap(name => st.theories(name).purge_edits) |
|
477 session.update(Document.Blobs.empty, purge_edits) |
|
478 |
|
479 ((purged, retained), st.remove_theories(purged)) |
|
480 }) |
|
481 } |
530 } |
482 } |
531 } |