From 960f3450c5ff07e000a5bd9c59d6203d67d932e8 Mon Sep 17 00:00:00 2001 From: Nikos Gorogiannis Date: Wed, 27 Nov 2024 12:16:53 -0800 Subject: [PATCH] [sqlite] cd rather than symlink db paths Summary: Reuse technique originally for unix sockets: cd into the directory with the database file, open it, then cd back. This avoids the Sqlite limits on maximum path length entirely. Reviewed By: jvillard Differential Revision: D66544844 Privacy Context Container: L1208441 fbshipit-source-id: 66d05cee5c85bc41c7f8fa5404dbefdc741fb4e9 --- infer/src/base/Database.ml | 34 ++++++++++++---------------------- infer/src/base/SqliteUtils.mli | 3 --- 2 files changed, 12 insertions(+), 25 deletions(-) diff --git a/infer/src/base/Database.ml b/infer/src/base/Database.ml index 45718ff3e73..474216e59b7 100644 --- a/infer/src/base/Database.ml +++ b/infer/src/base/Database.ml @@ -138,31 +138,20 @@ type location = Primary | Secondary of string [@@deriving show {with_path= false let results_dir_get_path entry = ResultsDirEntryName.get_path ~results_dir:Config.results_dir entry let get_db_path location id = - match location with - | Secondary file -> - file - | Primary -> - let path_to_db = results_dir_get_path (get_db_entry id) in - if String.length path_to_db > SqliteUtils.sqlite_max_path_length then ( - let link_name = Filename.temp_file "infer-merge-sqlite-trampoline" ".db" in - Unix.unlink link_name ; - Unix.symlink ~target:(Filename.dirname path_to_db) ~link_name ; - Filename.concat link_name (Filename.basename path_to_db) ) - else path_to_db + match location with Secondary file -> file | Primary -> results_dir_get_path (get_db_entry id) + + +let do_in_db_dir db_path ~f = + let dir = Filename.dirname db_path in + let base_name = Filename.basename db_path in + Utils.do_in_dir ~dir ~f:(fun () -> f base_name) let create_db location id = let final_db_path = get_db_path location id in let pid = Unix.getpid () in - let in_dir = - (* if the length of the path to the results directory is greater than Sqlite's limit - then create the DB in [$TMPDIR] otherwise in [results_dir/tmp] *) - let results_temp_dir = results_dir_get_path Temporary in - if String.length results_temp_dir > SqliteUtils.sqlite_max_path_length - 50 then None - else Some results_temp_dir - in let temp_db_path = - Filename.temp_file ?in_dir + Filename.temp_file ~in_dir:(results_dir_get_path Temporary) ( match id with | CaptureDatabase -> "capture." ^ Pid.to_string pid ^ ".db" @@ -170,7 +159,7 @@ let create_db location id = "results." ^ Pid.to_string pid ^ ".db" ) ".tmp" in - let db = Sqlite3.db_open ~mutex:`FULL temp_db_path in + let db = do_in_db_dir temp_db_path ~f:(fun db_path -> Sqlite3.db_open ~mutex:`FULL db_path) in SqliteUtils.exec db ~log:"sqlite page size" ~stmt:(Printf.sprintf "PRAGMA page_size=%d" Config.sqlite_page_size) ; create_tables db id ; @@ -315,8 +304,9 @@ end = struct db_close_1 id ; let db_path = get_db_path location id in let db = - Sqlite3.db_open ~mode:`NO_CREATE ~cache:`PRIVATE ~mutex:`FULL ?vfs:Config.sqlite_vfs ~uri:true - db_path + do_in_db_dir db_path ~f:(fun db_path -> + Sqlite3.db_open ~mode:`NO_CREATE ~cache:`PRIVATE ~mutex:`FULL ?vfs:Config.sqlite_vfs + ~uri:true db_path ) in Sqlite3.busy_timeout db Config.sqlite_lock_timeout ; SqliteUtils.exec db ~log:"mmap" diff --git a/infer/src/base/SqliteUtils.mli b/infer/src/base/SqliteUtils.mli index 6427d6e6a0a..dd5cd64e4a0 100644 --- a/infer/src/base/SqliteUtils.mli +++ b/infer/src/base/SqliteUtils.mli @@ -14,9 +14,6 @@ exception Error of string (** Raised from serializers when final size exceeds Sqlite3 limits (normally 1000_000_000 bytes). *) exception DataTooBig -val sqlite_max_path_length : int -(** an underapproximation of the maximum path length allowed in sqlite *) - val check_result_code : Sqlite3.db -> log:string -> Sqlite3.Rc.t -> unit (** Assert that the result is either [Sqlite3.Rc.OK] or [Sqlite3.Rc.ROW]. If the result is not valid, raise {!Error}. *)