11open Prelude
22
33(* TODO: GoblintDir *)
4- let version_map_filename = " version.data"
5- let cil_file_name = " ast.data"
6- let solver_data_file_name = " solver.data"
7- let analysis_data_file_name = " analysis.data"
4+ let incremental_data_file_name = " analysis.data"
85let results_dir = " results"
9- let results_tmp_dir = " results_tmp"
106
117type operation = Save | Load
128
@@ -21,9 +17,6 @@ let gob_directory op =
2117let gob_results_dir op =
2218 Fpath. (gob_directory op / results_dir)
2319
24- let gob_results_tmp_dir op =
25- Fpath. (gob_directory op / results_tmp_dir)
26-
2720let server () = GobConfig. get_bool " server.enabled"
2821
2922let marshal obj fileName =
@@ -43,49 +36,70 @@ let results_exist () =
4336 let r_str = Fpath. to_string r in
4437 Sys. file_exists r_str && Sys. is_directory r_str
4538
46- (* Convenience enumeration of the different data types we store for incremental analysis, so file-name logic is concentrated in one place *)
47- type incremental_data_kind = SolverData | CilFile | VersionData | AnalysisData
48-
49- let type_to_file_name = function
50- | SolverData -> solver_data_file_name
51- | CilFile -> cil_file_name
52- | VersionData -> version_map_filename
53- | AnalysisData -> analysis_data_file_name
54-
55- (* * Used by the server mode to avoid serializing the solver state to the filesystem *)
56- let server_solver_data : Obj.t option ref = ref None
57- let server_analysis_data : Obj.t option ref = ref None
58-
59- (* * Loads data for incremental runs from the appropriate file *)
60- let load_data (data_type : incremental_data_kind ) =
61- if server () then
62- match data_type with
63- | SolverData -> ! server_solver_data |> Option. get |> Obj. obj
64- | AnalysisData -> ! server_analysis_data |> Option. get |> Obj. obj
65- | _ -> failwith " Can only load solver and analysis data"
66- else
67- let p = Fpath. (gob_results_dir Load / type_to_file_name data_type) in
68- unmarshal p
69-
70- (* * Stores data for future incremental runs at the appropriate file, given the data and what kind of data it is. *)
71- let store_data (data : 'a ) (data_type : incremental_data_kind ) =
72- if server () then
73- match data_type with
74- | SolverData -> server_solver_data := Some (Obj. repr data)
75- | AnalysisData -> server_analysis_data := Some (Obj. repr data)
76- | _ -> ()
77- else (
39+ (* * Module to cache the data for incremental analaysis during a run, before it is stored to disk, as well as for the server mode *)
40+ module Cache = struct
41+ type t = {
42+ mutable solver_data : Obj .t option ;
43+ mutable analysis_data : Obj .t option ;
44+ mutable version_data : MaxIdUtil .max_ids option ;
45+ mutable cil_file : Cil .file option ;
46+ }
47+
48+ let data = ref {
49+ solver_data = None ;
50+ analysis_data = None ;
51+ version_data = None ;
52+ cil_file = None ;
53+ }
54+
55+ (* * GADT that may be used to query data from and pass data to the cache. *)
56+ type _ data_query =
57+ | SolverData : _ data_query
58+ | CilFile : Cil .file data_query
59+ | VersionData : MaxIdUtil .max_ids data_query
60+ | AnalysisData : _ data_query
61+
62+ (* * Loads data for incremental runs from the appropriate file *)
63+ let load_data () =
64+ let p = Fpath. (gob_results_dir Load / incremental_data_file_name) in
65+ let loaded_data = unmarshal p in
66+ data := loaded_data
67+
68+ (* * Stores data for future incremental runs at the appropriate file. *)
69+ let store_data () =
7870 GobSys. mkdir_or_exists (gob_directory Save );
79- let d = gob_results_tmp_dir Save in
71+ let d = gob_results_dir Save in
8072 GobSys. mkdir_or_exists d;
81- let p = Fpath. (d / type_to_file_name data_type) in
82- marshal data p)
83-
84- (* * Deletes previous analysis results and moves the freshly created results there.*)
85- let move_tmp_results_to_results () =
86- let op = Save in
87- if not (server () ) then (
88- if Sys. file_exists (Fpath. to_string (gob_results_dir op)) then begin
89- Goblintutil. rm_rf (gob_results_dir op);
90- end ;
91- Sys. rename (Fpath. to_string (gob_results_tmp_dir op)) (Fpath. to_string (gob_results_dir op)))
73+ let p = Fpath. (d / incremental_data_file_name) in
74+ marshal ! data p
75+
76+ (* * Update the incremental data in the in-memory cache *)
77+ let update_data: type a. a data_query -> a -> unit = fun q d -> match q with
78+ | SolverData -> ! data.solver_data < - Some (Obj. repr d)
79+ | AnalysisData -> ! data.analysis_data < - Some (Obj. repr d)
80+ | VersionData -> ! data.version_data < - Some d
81+ | CilFile -> ! data.cil_file < - Some d
82+
83+ (* * Reset some incremental data in the in-memory cache to [None]*)
84+ let reset_data : type a. a data_query -> unit = function
85+ | SolverData -> ! data.solver_data < - None
86+ | AnalysisData -> ! data.analysis_data < - None
87+ | VersionData -> ! data.version_data < - None
88+ | CilFile -> ! data.cil_file < - None
89+
90+ (* * Get incremental data from the in-memory cache wrapped in an optional.
91+ To populate the in-memory cache with data, call [load_data] first. *)
92+ let get_opt_data : type a. a data_query -> a option = function
93+ | SolverData -> Option. map Obj. obj ! data.solver_data
94+ | AnalysisData -> Option. map Obj. obj ! data.analysis_data
95+ | VersionData -> ! data.version_data
96+ | CilFile -> ! data.cil_file
97+
98+ (* * Get incremental data from the in-memory cache.
99+ Same as [get_opt_data], except not yielding an optional and failing when the requested data is not present. *)
100+ let get_data : type a. a data_query -> a =
101+ fun a ->
102+ match get_opt_data a with
103+ | Some d -> d
104+ | None -> failwith " Requested data is not loaded."
105+ end
0 commit comments