@ -9,7 +9,6 @@
open ! IStd
open ! IStd
module F = Format
module F = Format
module L = Logging
module L = Logging
module CLOpt = CommandLineOption
module Stats = struct
module Stats = struct
type t =
type t =
@ -69,6 +68,8 @@ include struct
[ @@ deriving fields ]
[ @@ deriving fields ]
end
end
type full_summary = t
let get_status summary = summary . status
let get_status summary = summary . status
let get_proc_desc summary = summary . proc_desc
let get_proc_desc summary = summary . proc_desc
@ -118,9 +119,58 @@ let pp_html source fmt summary =
F . fprintf fmt " </LISTING>@ \n "
F . fprintf fmt " </LISTING>@ \n "
module SQLite = SqliteUtils . MarshalledDataNOTForComparison ( struct
module ReportSummary = struct
type nonrec t = t
type t = { loc : Location . t ; cost_opt : CostDomain . summary option ; err_log : Errlog . t }
end )
let of_full_summary ( f : full_summary ) =
( { loc = get_loc f ; cost_opt = f . payloads . Payloads . cost ; err_log = f . err_log } : t )
module SQLite = SqliteUtils . MarshalledDataNOTForComparison ( struct
type nonrec t = t
end )
end
module AnalysisSummary = struct
include struct
(* ignore dead modules added by @@deriving fields *)
[ @@ @ warning " -60 " ]
type t =
{ payloads : Payloads . t
; mutable sessions : int
; stats : Stats . t
; status : Status . t
; proc_desc : Procdesc . t
; mutable callee_pnames : Procname . Set . t }
[ @@ deriving fields ]
end
let of_full_summary ( f : full_summary ) =
( { payloads = f . payloads
; sessions = f . sessions
; stats = f . stats
; status = f . status
; proc_desc = f . proc_desc
; callee_pnames = f . callee_pnames }
: t )
module SQLite = SqliteUtils . MarshalledDataNOTForComparison ( struct
type nonrec t = t
end )
end
let mk_full_summary ( report_summary : ReportSummary . t ) ( analysis_summary : AnalysisSummary . t ) =
( { payloads = analysis_summary . payloads
; sessions = analysis_summary . sessions
; stats = analysis_summary . stats
; status = analysis_summary . status
; proc_desc = analysis_summary . proc_desc
; callee_pnames = analysis_summary . callee_pnames
; err_log = report_summary . err_log }
: full_summary )
module OnDisk = struct
module OnDisk = struct
type cache = t Procname . Hash . t
type cache = t Procname . Hash . t
@ -181,15 +231,18 @@ module OnDisk = struct
let spec_of_procname =
let spec_of_procname =
let load_statement =
let load_statement =
ResultsDatabase . register_statement " SELECT spec FROM specs WHERE proc_name = :k "
ResultsDatabase . register_statement
" SELECT analysis_summary, report_summary FROM specs WHERE proc_name = :k "
in
in
fun proc_name ->
fun proc_name ->
ResultsDatabase . with_registered_statement load_statement ~ f : ( fun db load_stmt ->
ResultsDatabase . with_registered_statement load_statement ~ f : ( fun db load_stmt ->
Sqlite3 . bind load_stmt 1 ( Procname . SQLite . serialize proc_name )
Sqlite3 . bind load_stmt 1 ( Procname . SQLite . serialize proc_name )
| > SqliteUtils . check_result_code db ~ log : " load proc specs bind proc_name " ;
| > SqliteUtils . check_result_code db ~ log : " load proc specs bind proc_name " ;
SqliteUtils . result_single_column_option ~ finalize : false ~ log : " load proc specs run " db
SqliteUtils . result_option ~ finalize : false db ~ log : " load proc specs run " load_stmt
load_stmt
~ read_row : ( fun stmt ->
| > Option . map ~ f : SQLite . deserialize )
let analysis_summary = Sqlite3 . column stmt 0 | > AnalysisSummary . SQLite . deserialize in
let report_summary = Sqlite3 . column stmt 1 | > ReportSummary . SQLite . deserialize in
mk_full_summary report_summary analysis_summary ) )
(* * Load procedure summary for the given procedure name and update spec table *)
(* * Load procedure summary for the given procedure name and update spec table *)
@ -236,9 +289,12 @@ module OnDisk = struct
( specs_filename_of_procname proc_name )
( specs_filename_of_procname proc_name )
~ data : final_summary
~ data : final_summary
else
else
let analysis_summary = AnalysisSummary . of_full_summary final_summary in
let report_summary = ReportSummary . of_full_summary final_summary in
DBWriter . store_spec
DBWriter . store_spec
~ proc_name : ( Procname . SQLite . serialize proc_name )
~ proc_name : ( Procname . SQLite . serialize proc_name )
~ spec : ( SQLite . serialize final_summary )
~ analysis_summary : ( AnalysisSummary . SQLite . serialize analysis_summary )
~ report_summary : ( ReportSummary . SQLite . serialize report_summary )
let reset proc_desc =
let reset proc_desc =
@ -274,39 +330,56 @@ module OnDisk = struct
else DBWriter . delete_spec ~ proc_name : ( Procname . SQLite . serialize pname )
else DBWriter . delete_spec ~ proc_name : ( Procname . SQLite . serialize pname )
let iter_specs =
let iter_filtered_specs ~ filter ~ f =
let iter_statement =
let db = ResultsDatabase . get_database () in
(* NB the order is deterministic, but it is over a serialised value, so it is arbitrary *)
let dummy_source_file = SourceFile . invalid _ _ FILE__ in
ResultsDatabase . register_statement " SELECT spec FROM specs ORDER BY proc_name ASC "
(* NB the order is deterministic, but it is over a serialised value, so it is arbitrary *)
in
Sqlite3 . prepare db
fun ~ f ->
" SELECT proc_name, analysis_summary, report_summary FROM specs ORDER BY proc_name ASC "
ResultsDatabase . with_registered_statement iter_statement ~ f : ( fun db stmt ->
| > Container . iter ~ fold : ( SqliteUtils . result_fold_rows db ~ log : " iter over filtered specs " )
SqliteUtils . result_fold_single_column_rows ~ finalize : false db stmt
~ f : ( fun stmt ->
~ log : " iter over all specs " ~ init : () ~ f : ( fun () sqlite_spec ->
let proc_name = Sqlite3 . column stmt 0 | > Procname . SQLite . deserialize in
let summary : t = SQLite . deserialize sqlite_spec in
if filter dummy_source_file proc_name then
let () = f summary in
let analysis_summary = Sqlite3 . column stmt 1 | > AnalysisSummary . SQLite . deserialize in
() ) )
let report_summary = Sqlite3 . column stmt 2 | > ReportSummary . SQLite . deserialize in
let spec = mk_full_summary report_summary analysis_summary in
f spec )
let iter_ over_ filter ~ filter ~ f =
let iter_ filtered_report_summaries ~ filter ~ f =
let db = ResultsDatabase . get_database () in
let db = ResultsDatabase . get_database () in
let dummy_source_file = SourceFile . invalid _ _ FILE__ in
(* NB the order is deterministic, but it is over a serialised value, so it is arbitrary *)
(* NB the order is deterministic, but it is over a serialised value, so it is arbitrary *)
Sqlite3 . prepare db " SELECT proc_name, spec FROM specs ORDER BY proc_name ASC"
Sqlite3 . prepare db " SELECT proc_name, report_summary FROM specs ORDER BY proc_name ASC"
| > Container . iter ~ fold : ( SqliteUtils . result_fold_rows db ~ log : " iter over filtered specs " )
| > Container . iter ~ fold : ( SqliteUtils . result_fold_rows db ~ log : " iter over filtered specs " )
~ f : ( fun stmt ->
~ f : ( fun stmt ->
let proc_name = Sqlite3 . column stmt 0 | > Procname . SQLite . deserialize in
let proc_name = Sqlite3 . column stmt 0 | > Procname . SQLite . deserialize in
let spec = Sqlite3 . column stmt 1 | > SQLite . deserialize in
if filter dummy_source_file proc_name then
if filter ( SourceFile . invalid " invalid " ) proc_name then f spec )
let ( { loc ; cost_opt ; err_log } : ReportSummary . t ) =
Sqlite3 . column stmt 1 | > ReportSummary . SQLite . deserialize
in
f proc_name loc cost_opt err_log )
let make_filtered_iterator_from_config ~ iter ~ f =
let filter =
if Option . is_some Config . procedures_filter then (
if Config . test_filtering then (
Inferconfig . test () ;
L . exit 0 ) ;
Lazy . force Filtering . procedures_filter )
else fun _ _ -> true
in
iter ~ filter ~ f
let iter_report_summaries_from_config ~ f =
make_filtered_iterator_from_config ~ iter : iter_filtered_report_summaries ~ f
let iter_specs_from_config ~ f =
let iter_specs_from_config ~ f = make_filtered_iterator_from_config ~ iter : iter_filtered_specs ~ f
if CLOpt . is_originator && Option . is_some Config . procedures_filter then (
if Config . test_filtering then (
Inferconfig . test () ;
L . exit 0 ) ;
iter_over_filter ~ filter : ( Lazy . force Filtering . procedures_filter ) ~ f )
else iter_specs ~ f
let iter_specs ~ f = iter_filtered_specs ~ filter : ( fun _ _ -> true ) ~ f
let pp_specs_from_config fmt =
let pp_specs_from_config fmt =
iter_specs_from_config ~ f : ( fun summary ->
iter_specs_from_config ~ f : ( fun summary ->