410 session_content(false, Nil, session).check_errors.syntax |
411 session_content(false, Nil, session).check_errors.syntax |
411 |
412 |
412 |
413 |
413 /* jobs */ |
414 /* jobs */ |
414 |
415 |
415 private class Job(name: String, val info: Session_Info, output: Path, do_output: Boolean, |
416 private class Job(progress: Build.Progress, |
|
417 name: String, val info: Session_Info, output: Path, do_output: Boolean, |
416 verbose: Boolean, browser_info: Path) |
418 verbose: Boolean, browser_info: Path) |
417 { |
419 { |
418 // global browser info dir |
420 // global browser info dir |
419 if (info.options.bool("browser_info") && !(browser_info + Path.explode("index.html")).is_file) |
421 if (info.options.bool("browser_info") && !(browser_info + Path.explode("index.html")).is_file) |
420 { |
422 { |
477 exit "$RC" |
479 exit "$RC" |
478 """ |
480 """ |
479 } |
481 } |
480 |
482 |
481 private val (thread, result) = |
483 private val (thread, result) = |
482 Simple_Thread.future("build") { Isabelle_System.bash_env(info.dir.file, env, script) } |
484 Simple_Thread.future("build") { |
|
485 Isabelle_System.bash_env(info.dir.file, env, script, |
|
486 out_progress = (line: String) => |
|
487 if (line.startsWith(LOADING_THEORY)) |
|
488 progress.theory(line.substring(LOADING_THEORY.length))) |
|
489 } |
483 |
490 |
484 def terminate: Unit = thread.interrupt |
491 def terminate: Unit = thread.interrupt |
485 def is_finished: Boolean = result.is_finished |
492 def is_finished: Boolean = result.is_finished |
486 |
493 |
487 @volatile private var timeout = false |
494 @volatile private var timeout = false |
514 private val LOG = Path.explode("log") |
520 private val LOG = Path.explode("log") |
515 private def log(name: String): Path = LOG + Path.basic(name) |
521 private def log(name: String): Path = LOG + Path.basic(name) |
516 private def log_gz(name: String): Path = log(name).ext("gz") |
522 private def log_gz(name: String): Path = log(name).ext("gz") |
517 |
523 |
518 private val SESSION_PARENT_PATH = "\fSession.parent_path = " |
524 private val SESSION_PARENT_PATH = "\fSession.parent_path = " |
|
525 private val LOADING_THEORY = "\floading_theory = " |
519 |
526 |
520 sealed case class Log_Info(stats: List[Properties.T], timing: Properties.T) |
527 sealed case class Log_Info(stats: List[Properties.T], timing: Properties.T) |
521 |
528 |
522 def parse_log(text: String): Log_Info = |
529 def parse_log(text: String): Log_Info = |
523 { |
530 { |
632 else |
639 else |
633 running.find({ case (_, (_, job)) => job.is_finished }) match { |
640 running.find({ case (_, (_, job)) => job.is_finished }) match { |
634 case Some((name, (parent_heap, job))) => |
641 case Some((name, (parent_heap, job))) => |
635 //{{{ finish job |
642 //{{{ finish job |
636 |
643 |
637 val (out, err, rc) = job.join |
644 val res = job.join |
638 val out_lines = split_lines(out) |
645 progress.echo(res.err) |
639 progress.echo(Library.trim_line(err)) |
|
640 |
646 |
641 val (parent_path, heap) = |
647 val (parent_path, heap) = |
642 if (rc == 0) { |
648 if (res.rc == 0) { |
643 (output_dir + log(name)).file.delete |
649 (output_dir + log(name)).file.delete |
644 |
650 |
645 val sources = make_stamp(name) |
651 val sources = make_stamp(name) |
646 val heap = heap_stamp(job.output_path) |
652 val heap = heap_stamp(job.output_path) |
647 File.write_gzip(output_dir + log_gz(name), |
653 File.write_gzip(output_dir + log_gz(name), |
648 sources + "\n" + parent_heap + "\n" + heap + "\n" + out) |
654 sources + "\n" + parent_heap + "\n" + heap + "\n" + res.out) |
649 |
655 |
650 val parent_path = |
656 val parent_path = |
651 if (job.info.options.bool("browser_info")) |
657 if (job.info.options.bool("browser_info")) |
652 out_lines.find(_.startsWith(SESSION_PARENT_PATH)).map(line => |
658 res.out_lines.find(_.startsWith(SESSION_PARENT_PATH)).map(line => |
653 line.substring(SESSION_PARENT_PATH.length)) |
659 line.substring(SESSION_PARENT_PATH.length)) |
654 else None |
660 else None |
655 |
661 |
656 (parent_path, heap) |
662 (parent_path, heap) |
657 } |
663 } |
658 else { |
664 else { |
659 (output_dir + Path.basic(name)).file.delete |
665 (output_dir + Path.basic(name)).file.delete |
660 (output_dir + log_gz(name)).file.delete |
666 (output_dir + log_gz(name)).file.delete |
661 |
667 |
662 File.write(output_dir + log(name), out) |
668 File.write(output_dir + log(name), res.out) |
663 progress.echo(name + " FAILED") |
669 progress.echo(name + " FAILED") |
664 if (rc != 130) { |
670 if (res.rc != 130) { |
665 progress.echo("(see also " + (output_dir + log(name)).file.toString + ")") |
671 progress.echo("(see also " + (output_dir + log(name)).file.toString + ")") |
666 val lines = out_lines.filterNot(_.startsWith("\f")) |
672 val lines = res.out_lines.filterNot(_.startsWith("\f")) |
667 val tail = lines.drop(lines.length - 20 max 0) |
673 val tail = lines.drop(lines.length - 20 max 0) |
668 progress.echo("\n" + cat_lines(tail)) |
674 progress.echo("\n" + cat_lines(tail)) |
669 } |
675 } |
670 |
676 |
671 (None, no_heap) |
677 (None, no_heap) |
672 } |
678 } |
673 loop(pending - name, running - name, |
679 loop(pending - name, running - name, |
674 results + (name -> Result(false, parent_path, heap, rc))) |
680 results + (name -> Result(false, parent_path, heap, res.rc))) |
675 //}}} |
681 //}}} |
676 case None if (running.size < (max_jobs max 1)) => |
682 case None if (running.size < (max_jobs max 1)) => |
677 //{{{ check/start next job |
683 //{{{ check/start next job |
678 pending.dequeue(running.isDefinedAt(_)) match { |
684 pending.dequeue(running.isDefinedAt(_)) match { |
679 case Some((name, info)) => |
685 case Some((name, info)) => |
707 if (verbose) progress.echo("Skipping " + name + " ...") |
713 if (verbose) progress.echo("Skipping " + name + " ...") |
708 loop(pending - name, running, results + (name -> Result(false, None, heap, 1))) |
714 loop(pending - name, running, results + (name -> Result(false, None, heap, 1))) |
709 } |
715 } |
710 else if (parent_result.rc == 0) { |
716 else if (parent_result.rc == 0) { |
711 progress.echo((if (do_output) "Building " else "Running ") + name + " ...") |
717 progress.echo((if (do_output) "Building " else "Running ") + name + " ...") |
712 val job = new Job(name, info, output, do_output, verbose, browser_info) |
718 val job = new Job(progress, name, info, output, do_output, verbose, browser_info) |
713 loop(pending, running + (name -> (parent_result.heap, job)), results) |
719 loop(pending, running + (name -> (parent_result.heap, job)), results) |
714 } |
720 } |
715 else { |
721 else { |
716 progress.echo(name + " CANCELLED") |
722 progress.echo(name + " CANCELLED") |
717 loop(pending - name, running, results + (name -> Result(false, None, heap, 1))) |
723 loop(pending - name, running, results + (name -> Result(false, None, heap, 1))) |