-
Notifications
You must be signed in to change notification settings - Fork 284
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
IH-577 Implement v7 UUID generation #5866
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -131,21 +131,46 @@ let read_bytes dev n = | |
|
||
let make_uuid_urnd () = of_bytes (read_bytes dev_urandom_fd 16) |> Option.get | ||
|
||
(** Use non-CSPRNG by default, for CSPRNG see {!val:make_uuid_urnd} *) | ||
let make_uuid_fast = | ||
let uuid_state = Random.State.make_self_init () in | ||
(* State for random number generation. Random.State.t isn't thread safe, so | ||
only use this via with_non_csprng_state, which takes care of this. | ||
*) | ||
let rstate = Random.State.make_self_init () | ||
|
||
let rstate_m = Mutex.create () | ||
|
||
let with_non_csprng_state = | ||
(* On OCaml 5 we could use Random.State.split instead, | ||
and on OCaml 4 the mutex may not be strictly needed | ||
*) | ||
let m = Mutex.create () in | ||
let finally () = Mutex.unlock m in | ||
let gen = Uuidm.v4_gen uuid_state in | ||
fun () -> Mutex.lock m ; Fun.protect ~finally gen | ||
let finally () = Mutex.unlock rstate_m in | ||
fun f -> | ||
Mutex.lock rstate_m ; | ||
Fun.protect ~finally (f rstate) | ||
|
||
(** Use non-CSPRNG by default, for CSPRNG see {!val:make_uuid_urnd} *) | ||
let make_uuid_fast () = with_non_csprng_state Uuidm.v4_gen | ||
|
||
let make_default = ref make_uuid_urnd | ||
|
||
let make () = !make_default () | ||
|
||
let make_v7_uuid_from_parts time_ns rand_b = Uuidm.v7_ns ~time_ns ~rand_b | ||
|
||
let rand64 () = | ||
with_non_csprng_state (fun rstate () -> Random.State.bits64 rstate) | ||
|
||
let now_ns = | ||
let start = Mtime_clock.counter () in | ||
let t0 = | ||
let d, ps = Ptime_clock.now () |> Ptime.to_span |> Ptime.Span.to_d_ps in | ||
Int64.(add (mul (of_int d) 86_400_000_000_000L) (div ps 1000L)) | ||
in | ||
fun () -> | ||
let since_t0 = Mtime_clock.count start |> Mtime.Span.to_uint64_ns in | ||
Int64.add t0 since_t0 | ||
|
||
let make_v7_uuid () = make_v7_uuid_from_parts (now_ns ()) (rand64 ()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There are only 2048 possible valued for the rand64, how are we avoiding duplicates? In general, I'd prefer to use a counter here, it would ensure that no duplicates are ever produced, and that sequentially-created uuids are properly ordered. However, the rates needed for this to happen are rather high, and I doubt this affects how the toolstack will use the uuids, this can be changed at a later time if we found it's an impediment. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I'd been assuming that |
||
|
||
type cookie = string | ||
|
||
let make_cookie () = | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that both
{ptime,mtime}.clock.os
are deprecated use{ptime,mtime}.clock
if you are using the latest version (also clocks are made to re-export the base package so you can also specify only those if you wish so). See https://discuss.ocaml.org/t/ann-ptime-1-2-0-mtime-2-1-0-qrc-0-2-0/15268