495 if (is_pure(name)) Options.encode(info.options) |
495 if (is_pure(name)) Options.encode(info.options) |
496 else |
496 else |
497 { |
497 { |
498 import XML.Encode._ |
498 import XML.Encode._ |
499 pair(list(properties), pair(bool, pair(Options.encode, pair(bool, pair(Path.encode, |
499 pair(list(properties), pair(bool, pair(Options.encode, pair(bool, pair(Path.encode, |
500 pair(string, pair(string, list(pair(Options.encode, list(Path.encode))))))))))( |
500 pair(string, pair(string, pair(string, |
|
501 list(pair(Options.encode, list(Path.encode)))))))))))( |
501 (command_timings, (do_output, (info.options, (verbose, (browser_info, |
502 (command_timings, (do_output, (info.options, (verbose, (browser_info, |
502 (parent, (name, info.theories)))))))) |
503 (parent, (info.chapter, (name, info.theories))))))))) |
503 })) |
504 })) |
504 |
505 |
505 private val env = |
506 private val env = |
506 Map("INPUT" -> parent, "TARGET" -> name, "OUTPUT" -> Isabelle_System.standard_path(output), |
507 Map("INPUT" -> parent, "TARGET" -> name, "OUTPUT" -> Isabelle_System.standard_path(output), |
507 (if (is_pure(name)) "ISABELLE_PROCESS_OPTIONS" else "ARGS_FILE") -> |
508 (if (is_pure(name)) "ISABELLE_PROCESS_OPTIONS" else "ARGS_FILE") -> |
593 private val LOG = Path.explode("log") |
594 private val LOG = Path.explode("log") |
594 private def log(name: String): Path = LOG + Path.basic(name) |
595 private def log(name: String): Path = LOG + Path.basic(name) |
595 private def log_gz(name: String): Path = log(name).ext("gz") |
596 private def log_gz(name: String): Path = log(name).ext("gz") |
596 |
597 |
597 private val SESSION_NAME = "\fSession.name = " |
598 private val SESSION_NAME = "\fSession.name = " |
598 private val SESSION_PARENT_PATH = "\fSession.parent_path = " |
|
599 |
599 |
600 |
600 |
601 sealed case class Log_Info( |
601 sealed case class Log_Info( |
602 name: String, |
602 name: String, |
603 stats: List[Properties.T], |
603 stats: List[Properties.T], |
773 //{{{ finish job |
773 //{{{ finish job |
774 |
774 |
775 val res = job.join |
775 val res = job.join |
776 progress.echo(res.err) |
776 progress.echo(res.err) |
777 |
777 |
778 val (parent_path, heap) = |
778 val heap = |
779 if (res.rc == 0) { |
779 if (res.rc == 0) { |
780 (output_dir + log(name)).file.delete |
780 (output_dir + log(name)).file.delete |
781 |
781 |
782 val sources = make_stamp(name) |
782 val sources = make_stamp(name) |
783 val heap = heap_stamp(job.output_path) |
783 val heap = heap_stamp(job.output_path) |
784 File.write_gzip(output_dir + log_gz(name), |
784 File.write_gzip(output_dir + log_gz(name), |
785 sources + "\n" + parent_heap + "\n" + heap + "\n" + res.out) |
785 sources + "\n" + parent_heap + "\n" + heap + "\n" + res.out) |
786 |
786 |
787 val parent_path = |
787 heap |
788 if (job.info.options.bool("browser_info")) |
|
789 res.out_lines.find(_.startsWith(SESSION_PARENT_PATH)) |
|
790 .map(_.substring(SESSION_PARENT_PATH.length)) |
|
791 else None |
|
792 |
|
793 (parent_path, heap) |
|
794 } |
788 } |
795 else { |
789 else { |
796 (output_dir + Path.basic(name)).file.delete |
790 (output_dir + Path.basic(name)).file.delete |
797 (output_dir + log_gz(name)).file.delete |
791 (output_dir + log_gz(name)).file.delete |
798 |
792 |
803 val lines = res.out_lines.filterNot(_.startsWith("\f")) |
797 val lines = res.out_lines.filterNot(_.startsWith("\f")) |
804 val tail = lines.drop(lines.length - 20 max 0) |
798 val tail = lines.drop(lines.length - 20 max 0) |
805 progress.echo("\n" + cat_lines(tail)) |
799 progress.echo("\n" + cat_lines(tail)) |
806 } |
800 } |
807 |
801 |
808 (None, no_heap) |
802 no_heap |
809 } |
803 } |
810 loop(pending - name, running - name, |
804 loop(pending - name, running - name, |
811 results + (name -> Result(false, parent_path, heap, res.rc))) |
805 results + (name -> Result(false, heap, res.rc))) |
812 //}}} |
806 //}}} |
813 case None if (running.size < (max_jobs max 1)) => |
807 case None if (running.size < (max_jobs max 1)) => |
814 //{{{ check/start next job |
808 //{{{ check/start next job |
815 pending.dequeue(running.isDefinedAt(_)) match { |
809 pending.dequeue(running.isDefinedAt(_)) match { |
816 case Some((name, info)) => |
810 case Some((name, info)) => |
817 val parent_result = |
811 val parent_result = |
818 info.parent match { |
812 info.parent match { |
819 case None => Result(true, None, no_heap, 0) |
813 case None => Result(true, no_heap, 0) |
820 case Some(parent) => results(parent) |
814 case Some(parent) => results(parent) |
821 } |
815 } |
822 val output = output_dir + Path.basic(name) |
816 val output = output_dir + Path.basic(name) |
823 val do_output = build_heap || queue.is_inner(name) |
817 val do_output = build_heap || queue.is_inner(name) |
824 |
818 |
837 } |
831 } |
838 } |
832 } |
839 val all_current = current && parent_result.current |
833 val all_current = current && parent_result.current |
840 |
834 |
841 if (all_current) |
835 if (all_current) |
842 loop(pending - name, running, results + (name -> Result(true, None, heap, 0))) |
836 loop(pending - name, running, results + (name -> Result(true, heap, 0))) |
843 else if (no_build) { |
837 else if (no_build) { |
844 if (verbose) progress.echo("Skipping " + name + " ...") |
838 if (verbose) progress.echo("Skipping " + name + " ...") |
845 loop(pending - name, running, results + (name -> Result(false, None, heap, 1))) |
839 loop(pending - name, running, results + (name -> Result(false, heap, 1))) |
846 } |
840 } |
847 else if (parent_result.rc == 0 && !progress.stopped) { |
841 else if (parent_result.rc == 0 && !progress.stopped) { |
848 progress.echo((if (do_output) "Building " else "Running ") + name + " ...") |
842 progress.echo((if (do_output) "Building " else "Running ") + name + " ...") |
849 val job = |
843 val job = |
850 new Job(progress, name, info, output, do_output, verbose, browser_info, |
844 new Job(progress, name, info, output, do_output, verbose, browser_info, |
851 queue.command_timings(name)) |
845 queue.command_timings(name)) |
852 loop(pending, running + (name -> (parent_result.heap, job)), results) |
846 loop(pending, running + (name -> (parent_result.heap, job)), results) |
853 } |
847 } |
854 else { |
848 else { |
855 progress.echo(name + " CANCELLED") |
849 progress.echo(name + " CANCELLED") |
856 loop(pending - name, running, results + (name -> Result(false, None, heap, 1))) |
850 loop(pending - name, running, results + (name -> Result(false, heap, 1))) |
857 } |
851 } |
858 case None => sleep(); loop(pending, running, results) |
852 case None => sleep(); loop(pending, running, results) |
859 } |
853 } |
860 ///}}} |
854 ///}}} |
861 case None => sleep(); loop(pending, running, results) |
855 case None => sleep(); loop(pending, running, results) |
872 Map.empty[String, Result] |
866 Map.empty[String, Result] |
873 } |
867 } |
874 else loop(queue, Map.empty, Map.empty) |
868 else loop(queue, Map.empty, Map.empty) |
875 |
869 |
876 val session_entries = |
870 val session_entries = |
877 (for ((name, res) <- results.iterator if res.parent_path.isDefined) |
871 (for ((name, res) <- results.iterator) |
878 yield (res.parent_path.get, name)).toList.groupBy(_._1).map( |
872 yield (full_tree(name).chapter, name)).toList.groupBy(_._1).map( |
879 { case (p, es) => (p, es.map(_._2).sorted) }) |
873 { case (chapter, es) => (chapter, es.map(_._2).sorted) }) |
880 for ((p, names) <- session_entries) |
874 for ((chapter, names) <- session_entries) |
881 Present.update_index(browser_info + Path.explode(p), names) |
875 Present.update_chapter_index(browser_info, chapter, names) |
882 |
876 |
883 val rc = (0 /: results)({ case (rc1, (_, res)) => rc1 max res.rc }) |
877 val rc = (0 /: results)({ case (rc1, (_, res)) => rc1 max res.rc }) |
884 if (rc != 0 && (verbose || !no_build)) { |
878 if (rc != 0 && (verbose || !no_build)) { |
885 val unfinished = |
879 val unfinished = |
886 (for ((name, res) <- results.iterator if res.rc != 0) yield name).toList |
880 (for ((name, res) <- results.iterator if res.rc != 0) yield name).toList |