426 val FINISHED = Value("finished") |
426 val FINISHED = Value("finished") |
427 val FAILED = Value("failed") |
427 val FAILED = Value("failed") |
428 val CANCELLED = Value("cancelled") |
428 val CANCELLED = Value("cancelled") |
429 } |
429 } |
430 |
430 |
431 object Session_Entry |
|
432 { |
|
433 val encode: XML.Encode.T[Session_Entry] = (entry: Session_Entry) => |
|
434 { |
|
435 import XML.Encode._ |
|
436 pair(string, pair(list(string), pair(option(int), pair(Timing.encode, pair(Timing.encode, |
|
437 pair(list(properties), pair(option(long), string)))))))( |
|
438 entry.chapter, (entry.groups, (entry.threads, (entry.timing, (entry.ml_timing, |
|
439 (entry.ml_statistics, (entry.heap_size, entry.status.toString))))))) |
|
440 } |
|
441 val decode: XML.Decode.T[Session_Entry] = (body: XML.Body) => |
|
442 { |
|
443 import XML.Decode._ |
|
444 val (chapter, (groups, (threads, (timing, (ml_timing, (ml_statistics, (heap_size, status))))))) = |
|
445 pair(string, pair(list(string), pair(option(int), pair(Timing.decode, pair(Timing.decode, |
|
446 pair(list(properties), pair(option(long), string)))))))(body) |
|
447 Session_Entry(chapter, groups, threads, timing, ml_timing, ml_statistics, heap_size, |
|
448 Session_Status.withName(status)) |
|
449 } |
|
450 } |
|
451 |
|
452 sealed case class Session_Entry( |
431 sealed case class Session_Entry( |
453 chapter: String, |
432 chapter: String, |
454 groups: List[String], |
433 groups: List[String], |
455 threads: Option[Int], |
434 threads: Option[Int], |
456 timing: Timing, |
435 timing: Timing, |
462 def finished: Boolean = status == Session_Status.FINISHED |
441 def finished: Boolean = status == Session_Status.FINISHED |
463 } |
442 } |
464 |
443 |
465 object Build_Info |
444 object Build_Info |
466 { |
445 { |
467 val build_info = SQL.Column.bytes("build_info") |
446 val session_name = SQL.Column.string("session_name", primary_key = true) |
468 val table = SQL.Table("isabelle_build_log_build_info", List(Meta_Info.log_name, build_info)) |
447 val chapter = SQL.Column.string("chapter") |
469 |
448 val groups = SQL.Column.string("groups") |
470 def encode: XML.Encode.T[Build_Info] = (info: Build_Info) => |
449 val threads = SQL.Column.int("threads") |
471 { |
450 val timing = SQL.Column.bytes("timing") |
472 import XML.Encode._ |
451 val ml_timing = SQL.Column.bytes("ml_timing") |
473 list(pair(string, Session_Entry.encode))(info.sessions.toList) |
452 val ml_statistics = SQL.Column.bytes("ml_statistics") |
474 } |
453 val heap_size = SQL.Column.long("heap_size") |
475 def decode: XML.Decode.T[Build_Info] = (body: XML.Body) => |
454 val status = SQL.Column.string("status") |
476 { |
455 |
477 import XML.Decode._ |
456 val table = SQL.Table("isabelle_build_log_build_info", |
478 Build_Info(list(pair(string, Session_Entry.decode))(body).toMap) |
457 List(Meta_Info.log_name, session_name, chapter, groups, threads, timing, ml_timing, |
479 } |
458 ml_statistics, heap_size, status)) |
480 } |
459 } |
481 |
460 |
482 sealed case class Build_Info(sessions: Map[String, Session_Entry]) |
461 sealed case class Build_Info(sessions: Map[String, Session_Entry]) |
483 { |
462 { |
484 def session(name: String): Session_Entry = sessions(name) |
463 def session(name: String): Session_Entry = sessions(name) |
657 ssh = |
636 ssh = |
658 if (ssh_host == "") None |
637 if (ssh_host == "") None |
659 else Some(SSH.init_context(options).open_session(ssh_host, ssh_user, port))) |
638 else Some(SSH.init_context(options).open_session(ssh_host, ssh_user, port))) |
660 } |
639 } |
661 |
640 |
662 def compress_build_info(build_info: Build_Info, options: XZ.Options = XZ.options()): Bytes = |
|
663 Bytes(YXML.string_of_body(Build_Info.encode(build_info))).compress(options) |
|
664 |
|
665 def uncompress_build_info(bytes: Bytes): Build_Info = |
|
666 Build_Info.decode(xml_cache.body(YXML.parse_body(bytes.uncompress().text))) |
|
667 |
|
668 def filter_files(db: SQL.Database, table: SQL.Table, files: List[JFile]): List[JFile] = |
641 def filter_files(db: SQL.Database, table: SQL.Table, files: List[JFile]): List[JFile] = |
669 { |
642 { |
670 val key = Meta_Info.log_name |
643 val key = Meta_Info.log_name |
671 val known_files = |
644 val known_files = |
672 using(db.select_statement(table, List(key)))(stmt => |
645 using(db.select_statement(table, List(key)))(stmt => |
714 using(db.insert_statement(Build_Info.table))(stmt => |
687 using(db.insert_statement(Build_Info.table))(stmt => |
715 { |
688 { |
716 for (file <- filter_files(db, Build_Info.table, files)) { |
689 for (file <- filter_files(db, Build_Info.table, files)) { |
717 val log_file = Log_File(file) |
690 val log_file = Log_File(file) |
718 val build_info = log_file.parse_build_info() |
691 val build_info = log_file.parse_build_info() |
719 |
692 for ((session_name, session) <- build_info.sessions.iterator) { |
720 db.set_string(stmt, 1, log_file.name) |
693 db.set_string(stmt, 1, log_file.name) |
721 db.set_bytes(stmt, 2, compress_build_info(build_info)) |
694 db.set_string(stmt, 2, session_name) |
722 |
695 db.set_string(stmt, 3, session.chapter) |
723 stmt.execute() |
696 db.set_string(stmt, 4, cat_lines(session.groups)) |
|
697 db.set_int(stmt, 5, session.threads) |
|
698 db.set_bytes(stmt, 6, Timing.write(session.timing)) |
|
699 db.set_bytes(stmt, 7, Timing.write(session.ml_timing)) |
|
700 db.set_bytes(stmt, 8, compress_properties(session.ml_statistics)) |
|
701 db.set_long(stmt, 9, session.heap_size) |
|
702 db.set_string(stmt, 10, session.status.toString) |
|
703 stmt.execute() |
|
704 } |
724 } |
705 } |
725 }) |
706 }) |
726 } |
707 } |
727 } |
708 } |
728 } |
709 } |