show failed sessions on main page;
authorwenzelm
Sun, 21 May 2017 23:07:20 +0200
changeset 65893 20656a4709d6
parent 65892 bbad8162d678
child 65894 54f621d5fa00
show failed sessions on main page;
src/Pure/Admin/build_status.scala
--- a/src/Pure/Admin/build_status.scala	Sun May 21 22:57:46 2017 +0200
+++ b/src/Pure/Admin/build_status.scala	Sun May 21 23:07:20 2017 +0200
@@ -33,7 +33,10 @@
       Build_Log.Data.universal_table.select(columns, distinct = true,
         sql = "WHERE " +
           Build_Log.Data.pull_date + " > " + Build_Log.Data.recent_time(days(options)) + " AND " +
-          Build_Log.Data.status + " = " + SQL.string(Build_Log.Session_Status.finished.toString) +
+          SQL.member(Build_Log.Data.status.ident,
+            List(
+              Build_Log.Session_Status.finished.toString,
+              Build_Log.Session_Status.failed.toString)) +
           (if (only_sessions.isEmpty) ""
            else " AND " + SQL.member(Build_Log.Data.session_name.ident, only_sessions)) +
           " AND " + SQL.enclose(sql) +
@@ -66,6 +69,10 @@
   sealed case class Data(date: Date, entries: List[Data_Entry])
   sealed case class Data_Entry(
     name: String, hosts: List[String], stretch: Double, sessions: List[Session])
+  {
+    def failed_sessions: List[Session] =
+      sessions.filter(_.head.failed).sortBy(_.name)
+  }
   sealed case class Session(
     name: String, threads: Int, entries: List[Entry], ml_statistics: ML_Statistics)
   {
@@ -74,10 +81,12 @@
     def head: Entry = entries.head
     def order: Long = - head.timing.elapsed.ms
 
-    def check_timing: Boolean = entries.length >= 3
+    def finished_entries: List[Entry] = entries.filter(_.finished)
+
+    def check_timing: Boolean = finished_entries.length >= 3
     def check_heap: Boolean =
-      entries.length >= 3 &&
-      entries.forall(entry =>
+      finished_entries.length >= 3 &&
+      finished_entries.forall(entry =>
         entry.maximum_heap > 0 ||
         entry.average_heap > 0 ||
         entry.stored_heap > 0)
@@ -90,7 +99,12 @@
     ml_timing: Timing,
     maximum_heap: Long,
     average_heap: Long,
-    stored_heap: Long)
+    stored_heap: Long,
+    status: Build_Log.Session_Status.Value)
+  {
+    def finished: Boolean = status == Build_Log.Session_Status.finished
+    def failed: Boolean = status == Build_Log.Session_Status.failed
+  }
 
   sealed case class Image(name: String, width: Int, height: Int)
   {
@@ -134,7 +148,8 @@
             Build_Log.Data.ml_timing_elapsed,
             Build_Log.Data.ml_timing_cpu,
             Build_Log.Data.ml_timing_gc,
-            Build_Log.Data.heap_size) :::
+            Build_Log.Data.heap_size,
+            Build_Log.Data.status) :::
           (if (ml_statistics) List(Build_Log.Data.ml_statistics) else Nil)
 
         val Threads_Option = """threads\s*=\s*(\d+)""".r
@@ -193,7 +208,8 @@
                     Build_Log.Data.ml_timing_gc),
                 maximum_heap = ml_stats.maximum_heap_size,
                 average_heap = ml_stats.average_heap_size,
-                stored_heap = ML_Statistics.heap_scale(res.long(Build_Log.Data.heap_size)))
+                stored_heap = ML_Statistics.heap_scale(res.long(Build_Log.Data.heap_size)),
+                status = Build_Log.Session_Status.withName(res.string(Build_Log.Data.status)))
 
             val sessions = data_entries.getOrElse(data_name, Map.empty)
             val entries = sessions.get(session_name).map(_.entries) getOrElse Nil
@@ -240,8 +256,17 @@
             List(HTML.text("status date:") -> HTML.text(data.date.toString))))),
         HTML.par(
           List(HTML.itemize(data.entries.map({ case data_entry =>
-            List(HTML.link(clean_name(data_entry.name) + "/index.html",
-              HTML.text(data_entry.name))) }))))))
+            List(
+              HTML.link(clean_name(data_entry.name) + "/index.html",
+                HTML.text(data_entry.name))) :::
+            (data_entry.failed_sessions match {
+              case Nil => Nil
+              case sessions =>
+                HTML.break ::: List(HTML.error_message_span("Failed:")) :::
+                HTML.text(" " +
+                  commas(sessions.map(s => s.name + " (" + s.head.isabelle_version + ")")))
+            })
+          }))))))
 
     for (data_entry <- data.entries) {
       val data_name = data_entry.name
@@ -263,7 +288,7 @@
 
               File.write(data_file,
                 cat_lines(
-                  session.entries.map(entry =>
+                  session.finished_entries.map(entry =>
                     List(entry.pull_date.unix_epoch,
                       entry.timing.elapsed.minutes,
                       entry.timing.resources.minutes,
@@ -274,7 +299,7 @@
                       entry.stored_heap).mkString(" "))))
 
               val max_time =
-                ((0.0 /: session.entries){ case (m, entry) =>
+                ((0.0 /: session.finished_entries){ case (m, entry) =>
                   m.max(entry.timing.elapsed.minutes).
                     max(entry.timing.resources.minutes).
                     max(entry.ml_timing.elapsed.minutes).