Skip to content

Commit a5c5bba

Browse files
committed
LMDB Disk Cache: guard queue operation in critical section
1 parent cacd914 commit a5c5bba

File tree

1 file changed

+21
-7
lines changed

1 file changed

+21
-7
lines changed

src/lib/disk_cache/lmdb/disk_cache.ml

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ module Make (Data : Binable.S) = struct
2323
; reusable_keys : int Queue.t
2424
(** A list of ids that are no longer reachable from OCaml runtime, but
2525
haven't been cleared inside the LMDB disk cache *)
26+
; queue_guard : Error_checking_mutex.t
2627
}
2728

2829
(** How big can the queue [reusable_keys] be before we do a cleanup *)
@@ -32,16 +33,25 @@ module Make (Data : Binable.S) = struct
3233
Async.Deferred.Result.map (Disk_cache_utils.initialize_dir path ~logger)
3334
~f:(fun path ->
3435
let env, db = Rw.create path in
35-
{ env; db; counter = ref 0; reusable_keys = Queue.create () } )
36+
{ env
37+
; db
38+
; counter = ref 0
39+
; reusable_keys = Queue.create ()
40+
; queue_guard = Error_checking_mutex.create ()
41+
} )
3642

3743
type id = { idx : int }
3844

3945
let get ({ env; db; _ } : t) ({ idx } : id) : Data.t =
4046
Rw.get ~env db idx |> Option.value_exn
4147

42-
let put ({ env; db; counter; reusable_keys } : t) (x : Data.t) : id =
48+
let put ({ env; db; counter; reusable_keys; queue_guard } : t) (x : Data.t) :
49+
id =
4350
let idx =
44-
match Queue.dequeue reusable_keys with
51+
match
52+
Error_checking_mutex.critical_section queue_guard ~f:(fun () ->
53+
Queue.dequeue reusable_keys )
54+
with
4555
| None ->
4656
(* We don't have reusable keys, assign a new one nobody ever used *)
4757
incr counter ; !counter - 1
@@ -57,10 +67,14 @@ module Make (Data : Binable.S) = struct
5767
critical section. LMDB critical section then will be re-entered if
5868
it's invoked directly in a GC hook.
5969
This causes mutex double-acquiring and node freezes. *)
60-
Queue.enqueue reusable_keys idx ) ;
61-
if Queue.length reusable_keys >= reuse_size_limit then (
62-
Queue.iter reusable_keys ~f:(fun to_remove -> Rw.remove ~env db to_remove) ;
63-
Queue.clear reusable_keys ) ;
70+
Error_checking_mutex.critical_section queue_guard ~f:(fun () ->
71+
Queue.enqueue reusable_keys idx ) ) ;
72+
73+
Error_checking_mutex.critical_section queue_guard ~f:(fun () ->
74+
if Queue.length reusable_keys >= reuse_size_limit then (
75+
Queue.iter reusable_keys ~f:(fun to_remove ->
76+
Rw.remove ~env db to_remove ) ;
77+
Queue.clear reusable_keys ) ) ;
6478
Rw.set ~env db idx x ;
6579
res
6680

0 commit comments

Comments
 (0)