Skip to content

Commit af3a084

Browse files
authored
Merge pull request #748 from goblint/issue_357_new
Store all incremental data into single file
2 parents 529a650 + c3962dc commit af3a084

File tree

5 files changed

+80
-69
lines changed

5 files changed

+80
-69
lines changed

src/framework/control.ml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -312,11 +312,11 @@ struct
312312

313313
GU.global_initialization := true;
314314
GU.earlyglobs := get_bool "exp.earlyglobs";
315-
let marshal =
315+
let marshal: Spec.marshal option =
316316
if get_string "load_run" <> "" then
317317
Some (Serialize.unmarshal Fpath.(v (get_string "load_run") / "spec_marshal"))
318318
else if Serialize.results_exist () && get_bool "incremental.load" then
319-
Some (Serialize.load_data Serialize.AnalysisData)
319+
Some (Serialize.Cache.(get_data AnalysisData))
320320
else
321321
None
322322
in
@@ -475,7 +475,7 @@ struct
475475
Goblintutil.should_warn := get_string "warn_at" = "early" || gobview;
476476
let (lh, gh), solver_data = Stats.time "solving" (Slvr.solve entrystates entrystates_global) startvars' in
477477
if GobConfig.get_bool "incremental.save" then
478-
Serialize.store_data solver_data Serialize.SolverData;
478+
Serialize.Cache.(update_data SolverData solver_data);
479479
if save_run_str <> "" then (
480480
let save_run = Fpath.v save_run_str in
481481
let analyses = Fpath.(save_run / "analyses.marshalled") in
@@ -691,8 +691,8 @@ struct
691691
Serialize.marshal marshal Fpath.(v save_run / "spec_marshal")
692692
);
693693
if get_bool "incremental.save" then (
694-
Serialize.store_data marshal Serialize.AnalysisData;
695-
Serialize.move_tmp_results_to_results ()
694+
Serialize.Cache.(update_data AnalysisData marshal);
695+
Serialize.Cache.store_data ()
696696
);
697697
if get_bool "dbg.verbose" && get_string "result" <> "none" then print_endline ("Generating output: " ^ get_string "result");
698698
Result.output (lazy local_xml) gh make_global_fast_xml file

src/incremental/maxIdUtil.ml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,3 @@ let get_file_max_ids (new_file: Cil.file) =
2828
let vid_max = ref 0 in
2929
Cil.iterGlobals new_file (fun g -> update_max_ids ~sid_max ~vid_max g);
3030
{max_sid = !sid_max; max_vid = !vid_max}
31-
32-
(** Loads the max sid and vid from a previous run *)
33-
let load_max_ids () =
34-
Serialize.load_data Serialize.VersionData

src/incremental/serialize.ml

Lines changed: 66 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,8 @@
11
open 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"
85
let results_dir = "results"
9-
let results_tmp_dir = "results_tmp"
106

117
type operation = Save | Load
128

@@ -21,9 +17,6 @@ let gob_directory op =
2117
let 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-
2720
let server () = GobConfig.get_bool "server.enabled"
2821

2922
let 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

src/maingoblint.ml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -512,9 +512,10 @@ let diff_and_rename current_file =
512512
end;
513513
let (changes, old_file, max_ids) =
514514
if Serialize.results_exist () && GobConfig.get_bool "incremental.load" then begin
515-
let old_file = Serialize.load_data Serialize.CilFile in
515+
Serialize.Cache.load_data ();
516+
let old_file = Serialize.Cache.(get_data CilFile) in
516517
let changes = CompareCIL.compareCilFiles old_file current_file in
517-
let max_ids = MaxIdUtil.load_max_ids () in
518+
let max_ids = Serialize.Cache.(get_data VersionData) in
518519
let max_ids = UpdateCil.update_ids old_file max_ids current_file changes in
519520
(changes, Some old_file, max_ids)
520521
end else begin
@@ -523,12 +524,12 @@ let diff_and_rename current_file =
523524
end
524525
in
525526
let solver_data = if Serialize.results_exist () && GobConfig.get_bool "incremental.load" && not (GobConfig.get_bool "incremental.only-rename")
526-
then Some (Serialize.load_data Serialize.SolverData)
527+
then Some Serialize.Cache.(get_data SolverData)
527528
else None
528529
in
529530
if GobConfig.get_bool "incremental.save" then begin
530-
Serialize.store_data current_file Serialize.CilFile;
531-
Serialize.store_data max_ids Serialize.VersionData
531+
Serialize.Cache.(update_data CilFile current_file);
532+
Serialize.Cache.(update_data VersionData max_ids);
532533
end;
533534
let old_data = match old_file, solver_data with
534535
| Some cil_file, Some solver_data -> Some ({solver_data}: Analyses.analyzed_data)

src/util/server.ml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ let virtual_changes file =
123123
in
124124
CompareCIL.compareCilFiles ~eq file file
125125

126-
let increment_data (s: t) file reparsed = match !Serialize.server_solver_data with
126+
let increment_data (s: t) file reparsed = match Serialize.Cache.get_opt_data SolverData with
127127
| Some solver_data when reparsed ->
128128
let changes = CompareCIL.compareCilFiles s.file file in
129129
let old_data = Some { Analyses.solver_data } in
@@ -142,8 +142,8 @@ let analyze ?(reset=false) (s: t) =
142142
if reset then (
143143
let max_ids = MaxIdUtil.get_file_max_ids file in
144144
s.max_ids <- max_ids;
145-
Serialize.server_solver_data := None;
146-
Serialize.server_analysis_data := None);
145+
Serialize.Cache.reset_data SolverData;
146+
Serialize.Cache.reset_data AnalysisData);
147147
let increment_data, fresh = increment_data s file reparsed in
148148
Cilfacade.reset_lazy ();
149149
WideningThresholds.reset_lazy ();

0 commit comments

Comments
 (0)