src/Pure/Admin/build_log.scala
changeset 65605 a6447eb6bc38
parent 65603 d6fe8a277576
child 65607 c937984c70e9
equal deleted inserted replaced
65604:637aa8e93cd7 65605:a6447eb6bc38
   280   /** digested meta info: produced by Admin/build_history in log.xz file **/
   280   /** digested meta info: produced by Admin/build_history in log.xz file **/
   281 
   281 
   282   object Meta_Info
   282   object Meta_Info
   283   {
   283   {
   284     val empty: Meta_Info = Meta_Info(Nil, Nil)
   284     val empty: Meta_Info = Meta_Info(Nil, Nil)
       
   285 
       
   286     val log_filename = SQL.Column.string("log_filename", primary_key = true)
       
   287     val settings = SQL.Column.bytes("settings")
       
   288 
       
   289     val table =
       
   290       SQL.Table("isabelle_build_log_meta_info", log_filename :: Prop.columns ::: List(settings))
   285   }
   291   }
   286 
   292 
   287   sealed case class Meta_Info(props: Properties.T, settings: List[(String, String)])
   293   sealed case class Meta_Info(props: Properties.T, settings: List[(String, String)])
   288   {
   294   {
   289     def is_empty: Boolean = props.isEmpty && settings.isEmpty
   295     def is_empty: Boolean = props.isEmpty && settings.isEmpty
   443     def finished: Boolean = status == Session_Status.FINISHED
   449     def finished: Boolean = status == Session_Status.FINISHED
   444   }
   450   }
   445 
   451 
   446   object Build_Info
   452   object Build_Info
   447   {
   453   {
       
   454     val build_info = SQL.Column.bytes("build_info")
       
   455     val table = SQL.Table("isabelle_build_log_build_info", List(Meta_Info.log_filename, build_info))
       
   456 
   448     def encode: XML.Encode.T[Build_Info] = (info: Build_Info) =>
   457     def encode: XML.Encode.T[Build_Info] = (info: Build_Info) =>
   449     {
   458     {
   450       import XML.Encode._
   459       import XML.Encode._
   451       list(pair(string, Session_Entry.encode))(info.sessions.toList)
   460       list(pair(string, Session_Entry.encode))(info.sessions.toList)
   452     }
   461     }
   614 
   623 
   615 
   624 
   616 
   625 
   617   /** persistent store **/
   626   /** persistent store **/
   618 
   627 
   619   object Info
       
   620   {
       
   621     val log_filename = SQL.Column.string("log_filename", primary_key = true)
       
   622     val settings = SQL.Column.bytes("settings")
       
   623     val build_info = SQL.Column.bytes("build_info")
       
   624 
       
   625     val table =
       
   626       SQL.Table("isabelle_build_log", log_filename :: Prop.columns ::: List(settings, build_info))
       
   627   }
       
   628 
       
   629   def store(options: Options): Store = new Store(options)
   628   def store(options: Options): Store = new Store(options)
   630 
   629 
   631   class Store private[Build_Log](options: Options) extends Properties.Store
   630   class Store private[Build_Log](options: Options) extends Properties.Store
   632   {
   631   {
   633     def open_database(
   632     def open_database(
   651       Bytes(YXML.string_of_body(Build_Info.encode(build_info))).compress(options)
   650       Bytes(YXML.string_of_body(Build_Info.encode(build_info))).compress(options)
   652 
   651 
   653     def uncompress_build_info(bytes: Bytes): Build_Info =
   652     def uncompress_build_info(bytes: Bytes): Build_Info =
   654       Build_Info.decode(xml_cache.body(YXML.parse_body(bytes.uncompress().text)))
   653       Build_Info.decode(xml_cache.body(YXML.parse_body(bytes.uncompress().text)))
   655 
   654 
   656     def filter_files(db: SQL.Database, files: List[JFile]): List[JFile] =
   655     def filter_files(db: SQL.Database, table: SQL.Table, files: List[JFile]): List[JFile] =
   657     {
   656     {
       
   657       val key = Meta_Info.log_filename
   658       val known_files =
   658       val known_files =
   659         using(db.select_statement(Info.table, List(Info.log_filename)))(stmt =>
   659         using(db.select_statement(table, List(key)))(stmt =>
   660           SQL.iterator(stmt.executeQuery)(rs => db.string(rs, Info.log_filename)).toSet)
   660           SQL.iterator(stmt.executeQuery)(rs => db.string(rs, key)).toSet)
   661 
   661 
   662       val unique_files =
   662       val unique_files =
   663         (Map.empty[String, JFile] /: files.iterator)({ case (m, file) =>
   663         (Map.empty[String, JFile] /: files.iterator)({ case (m, file) =>
   664           val name = file.getName
   664           val name = file.getName
   665           if (known_files(name)) m else m + (name -> file)
   665           if (known_files(name)) m else m + (name -> file)
   666         })
   666         })
   667 
   667 
   668       unique_files.iterator.map(_._2).toList
   668       unique_files.iterator.map(_._2).toList
   669     }
   669     }
   670 
   670 
   671     def write_infos(db: SQL.Database, files: List[JFile])
   671     def write_meta_info(db: SQL.Database, files: List[JFile])
   672     {
   672     {
   673       db.transaction {
   673       db.transaction {
   674         db.create_table(Info.table)
   674         db.create_table(Meta_Info.table)
   675 
   675 
   676         using(db.insert_statement(Info.table))(stmt =>
   676         using(db.insert_statement(Meta_Info.table))(stmt =>
   677         {
   677         {
   678           for (file <- filter_files(db, files)) {
   678           for (file <- filter_files(db, Meta_Info.table, files)) {
   679             val log_file = Log_File(file)
   679             val meta_info = Log_File(file).parse_meta_info()
   680             val meta_info = log_file.parse_meta_info()
       
   681             val build_info = log_file.parse_build_info()
       
   682 
       
   683             stmt.clearParameters
       
   684 
   680 
   685             db.set_string(stmt, 1, file.getName)
   681             db.set_string(stmt, 1, file.getName)
   686 
       
   687             for ((c, i) <- Prop.columns.zipWithIndex) {
   682             for ((c, i) <- Prop.columns.zipWithIndex) {
   688               if (c.T == SQL.Type.Date)
   683               if (c.T == SQL.Type.Date)
   689                 db.set_date(stmt, i + 2, meta_info.get_date(c).orNull)
   684                 db.set_date(stmt, i + 2, meta_info.get_date(c).orNull)
   690               else
   685               else
   691                 db.set_string(stmt, i + 2, meta_info.get(c).map(Prop.multiple_lines(_)).orNull)
   686                 db.set_string(stmt, i + 2, meta_info.get(c).map(Prop.multiple_lines(_)).orNull)
   692             }
   687             }
   693 
   688             db.set_bytes(stmt, Meta_Info.table.columns.length, encode_properties(meta_info.settings))
   694             val n = Info.table.columns.length
       
   695             db.set_bytes(stmt, n - 1, encode_properties(meta_info.settings))
       
   696             db.set_bytes(stmt, n, compress_build_info(build_info))
       
   697 
   689 
   698             stmt.execute()
   690             stmt.execute()
   699           }
   691           }
   700         })
   692         })
   701       }
   693       }
   702     }
   694     }
       
   695 
       
   696     def write_build_info(db: SQL.Database, files: List[JFile])
       
   697     {
       
   698       db.transaction {
       
   699         db.create_table(Build_Info.table)
       
   700 
       
   701         using(db.insert_statement(Build_Info.table))(stmt =>
       
   702         {
       
   703           for (file <- filter_files(db, Build_Info.table, files)) {
       
   704             val build_info = Log_File(file).parse_build_info()
       
   705 
       
   706             db.set_string(stmt, 1, file.getName)
       
   707             db.set_bytes(stmt, 2, compress_build_info(build_info))
       
   708 
       
   709             stmt.execute()
       
   710           }
       
   711         })
       
   712       }
       
   713     }
   703   }
   714   }
   704 }
   715 }