[sqlite] skeleton protocol for dbwriter

Summary: Developing the Sqlite-writer process further, a type `command` is introduced, which will used for sending instructions down a communications channel to the daemon.  For now, the commands are interpreted locally.

Reviewed By: skcho

Differential Revision: D16985056

fbshipit-source-id: 2aa20908d
master
Nikos Gorogiannis 6 years ago committed by Facebook Github Bot
parent 83aea33c68
commit 26823b22f1

@ -7,7 +7,8 @@
open! IStd open! IStd
let attribute_replace_statement = module Implementation = struct
let attribute_replace_statement =
(* The innermost SELECT returns either the current attributes_kind and source_file associated with (* The innermost SELECT returns either the current attributes_kind and source_file associated with
the given proc name, or default values of (-1,""). These default values have the property that the given proc name, or default values of (-1,""). These default values have the property that
they are always "less than" any legit value. More precisely, MAX ensures that some value is they are always "less than" any legit value. More precisely, MAX ensures that some value is
@ -40,8 +41,9 @@ let attribute_replace_statement =
|} |}
let replace_attributes ~pname_str ~pname ~akind ~source_file ~attributes ~proc_desc ~callees = let replace_attributes ~pname_str ~pname ~akind ~source_file ~attributes ~proc_desc ~callees =
ResultsDatabase.with_registered_statement attribute_replace_statement ~f:(fun db replace_stmt -> ResultsDatabase.with_registered_statement attribute_replace_statement
~f:(fun db replace_stmt ->
Sqlite3.bind replace_stmt 1 (* :pname *) pname Sqlite3.bind replace_stmt 1 (* :pname *) pname
|> SqliteUtils.check_result_code db ~log:"replace bind pname" ; |> SqliteUtils.check_result_code db ~log:"replace bind pname" ;
Sqlite3.bind replace_stmt 2 (* :proc_name_hum *) (Sqlite3.Data.TEXT pname_str) Sqlite3.bind replace_stmt 2 (* :proc_name_hum *) (Sqlite3.Data.TEXT pname_str)
@ -59,7 +61,7 @@ let replace_attributes ~pname_str ~pname ~akind ~source_file ~attributes ~proc_d
SqliteUtils.result_unit db ~finalize:false ~log:"Attributes.replace" replace_stmt ) SqliteUtils.result_unit db ~finalize:false ~log:"Attributes.replace" replace_stmt )
let source_file_store_statement = let source_file_store_statement =
ResultsDatabase.register_statement ResultsDatabase.register_statement
{| {|
INSERT OR REPLACE INTO source_files INSERT OR REPLACE INTO source_files
@ -67,7 +69,7 @@ let source_file_store_statement =
|} |}
let add_source_file ~source_file ~tenv ~integer_type_widths ~proc_names = let add_source_file ~source_file ~tenv ~integer_type_widths ~proc_names =
ResultsDatabase.with_registered_statement source_file_store_statement ~f:(fun db store_stmt -> ResultsDatabase.with_registered_statement source_file_store_statement ~f:(fun db store_stmt ->
Sqlite3.bind store_stmt 1 source_file Sqlite3.bind store_stmt 1 source_file
(* :source *) (* :source *)
@ -87,16 +89,16 @@ let add_source_file ~source_file ~tenv ~integer_type_widths ~proc_names =
SqliteUtils.result_unit ~finalize:false ~log:"Cfg.store" db store_stmt ) SqliteUtils.result_unit ~finalize:false ~log:"Cfg.store" db store_stmt )
let mark_all_source_files_stale_statement = let mark_all_source_files_stale_statement =
ResultsDatabase.register_statement "UPDATE source_files SET freshly_captured = 0" ResultsDatabase.register_statement "UPDATE source_files SET freshly_captured = 0"
let mark_all_source_files_stale () = let mark_all_source_files_stale () =
ResultsDatabase.with_registered_statement mark_all_source_files_stale_statement ResultsDatabase.with_registered_statement mark_all_source_files_stale_statement
~f:(fun db stmt -> SqliteUtils.result_unit db ~finalize:false ~log:"mark_all_stale" stmt) ~f:(fun db stmt -> SqliteUtils.result_unit db ~finalize:false ~log:"mark_all_stale" stmt)
let merge_procedures_table ~db_file = let merge_procedures_table ~db_file =
let db = ResultsDatabase.get_database () in let db = ResultsDatabase.get_database () in
(* Do the merge purely in SQL for great speed. The query works by doing a left join between the (* Do the merge purely in SQL for great speed. The query works by doing a left join between the
sub-table and the main one, and applying the same "more defined" logic as in Attributes in the sub-table and the main one, and applying the same "more defined" logic as in Attributes in the
@ -119,7 +121,7 @@ let merge_procedures_table ~db_file =
~log:(Printf.sprintf "copying procedures of database '%s'" db_file) ~log:(Printf.sprintf "copying procedures of database '%s'" db_file)
let merge_source_files_table ~db_file = let merge_source_files_table ~db_file =
let db = ResultsDatabase.get_database () in let db = ResultsDatabase.get_database () in
Sqlite3.exec db Sqlite3.exec db
{| {|
@ -131,18 +133,71 @@ let merge_source_files_table ~db_file =
~log:(Printf.sprintf "copying source_files of database '%s'" db_file) ~log:(Printf.sprintf "copying source_files of database '%s'" db_file)
let merge_dbs ~infer_out_src = let merge_dbs ~infer_out_src =
let db_file = infer_out_src ^/ ResultsDatabase.database_filename in let db_file = infer_out_src ^/ ResultsDatabase.database_filename in
let main_db = ResultsDatabase.get_database () in let main_db = ResultsDatabase.get_database () in
Sqlite3.exec main_db (Printf.sprintf "ATTACH '%s' AS attached" db_file) Sqlite3.exec main_db (Printf.sprintf "ATTACH '%s' AS attached" db_file)
|> SqliteUtils.check_result_code main_db ~log:(Printf.sprintf "attaching database '%s'" db_file) ; |> SqliteUtils.check_result_code main_db
~log:(Printf.sprintf "attaching database '%s'" db_file) ;
merge_procedures_table ~db_file ; merge_procedures_table ~db_file ;
merge_source_files_table ~db_file ; merge_source_files_table ~db_file ;
Sqlite3.exec main_db "DETACH attached" Sqlite3.exec main_db "DETACH attached"
|> SqliteUtils.check_result_code main_db ~log:(Printf.sprintf "detaching database '%s'" db_file) ; |> SqliteUtils.check_result_code main_db
~log:(Printf.sprintf "detaching database '%s'" db_file) ;
() ()
let canonicalize () = let canonicalize () =
let db = ResultsDatabase.get_database () in let db = ResultsDatabase.get_database () in
SqliteUtils.exec db ~log:"running VACUUM" ~stmt:"VACUUM" SqliteUtils.exec db ~log:"running VACUUM" ~stmt:"VACUUM"
end
module Command = struct
type t =
| ReplaceAttributes of
{ pname_str: string
; pname: Sqlite3.Data.t
; akind: int64
; source_file: Sqlite3.Data.t
; attributes: Sqlite3.Data.t
; proc_desc: Sqlite3.Data.t
; callees: Sqlite3.Data.t }
| AddSourceFile of
{ source_file: Sqlite3.Data.t
; tenv: Sqlite3.Data.t
; integer_type_widths: Sqlite3.Data.t
; proc_names: Sqlite3.Data.t }
| MarkAllSourceFilesStale
| MergeDBs of {infer_out_src: string}
| Vacuum
let execute = function
| ReplaceAttributes {pname_str; pname; akind; source_file; attributes; proc_desc; callees} ->
Implementation.replace_attributes ~pname_str ~pname ~akind ~source_file ~attributes
~proc_desc ~callees
| AddSourceFile {source_file; tenv; integer_type_widths; proc_names} ->
Implementation.add_source_file ~source_file ~tenv ~integer_type_widths ~proc_names
| MarkAllSourceFilesStale ->
Implementation.mark_all_source_files_stale ()
| MergeDBs {infer_out_src} ->
Implementation.merge_dbs ~infer_out_src
| Vacuum ->
Implementation.canonicalize ()
end
let perform cmd = Command.execute cmd
let replace_attributes ~pname_str ~pname ~akind ~source_file ~attributes ~proc_desc ~callees =
Command.ReplaceAttributes {pname_str; pname; akind; source_file; attributes; proc_desc; callees}
|> perform
let add_source_file ~source_file ~tenv ~integer_type_widths ~proc_names =
Command.AddSourceFile {source_file; tenv; integer_type_widths; proc_names} |> perform
let mark_all_source_files_stale () = perform Command.MarkAllSourceFilesStale
let merge_dbs ~infer_out_src = Command.MergeDBs {infer_out_src} |> perform
let canonicalize () = perform Command.Vacuum

Loading…
Cancel
Save