Skip to content
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

LMDB storage #16274

Merged
merged 14 commits into from
Nov 18, 2024
2 changes: 1 addition & 1 deletion src/dune-project
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
(package (name blake2))
(package (name blockchain_snark))
(package (name block_producer))
(package (name block_storage))
(package (name block_time))
(package (name bootstrap_controller))
(package (name bounded_types))
Expand Down Expand Up @@ -82,6 +81,7 @@
(package (name ledger_proof))
(package (name libp2p_ipc))
(package (name linked_tree))
(package (name lmdb_storage))
(package (name logger))
(package (name logproc_lib))
(package (name merkle_address))
Expand Down
46 changes: 46 additions & 0 deletions src/lib/lmdb_storage/conv.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
open Core_kernel

let uint32_be =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is how int32_be defined in

let int32_be =
    { flags =
        if Sys.big_endian && is_int_size 4
        then Flags.(integer_key + integer_dup + dup_fixed)
        else Flags.(dup_fixed)
    ; serialise = begin fun alloc x ->
        let a = alloc 4 in
        Bigstring.set_int32_be a 0 x;
        a
      end
    ; deserialise = begin fun a ->
        Bigstring.get_int32_be a 0
      end
    }

Notice the difference in flags. Specification of LMDB prescribes a certain pattern of usage for the flags: http://www.lmdb.tech/doc/group__mdb.html.

It seems like the check for Sys.big_endian && is_int_size 4 might actually be needed to ensure the code behaves well under all circumstances.

Lmdb.Conv.make
~flags:
Lmdb.Conv.Flags.(
if Sys.big_endian && Int.equal Sys.int_size 4 then
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@georgeee I used Sys.int_size instead of is_int_size, since i cannot find it anywhere. I'm not sure if the 4 is right here. Sys.int_size is measuring int size in bits (so it will be 63 on majority of os). Is is_int_size expressed in bits too ? in that case 4 looks very suspicious

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought a bit. It's unlikely that integer will be 4 bytes on any modern server. So let's just drop the edge case and have ~flags:Lmdb.Conv.Flags.dup_fixed

integer_key + integer_dup + dup_fixed
else dup_fixed)
~serialise:(fun alloc x ->
let a = alloc 4 in
Bigstring.set_uint32_be_exn a ~pos:0 x ;
a )
~deserialise:(Bigstring.get_uint32_be ~pos:0)
()

let uint8 =
Lmdb.Conv.make ~flags:Lmdb.Conv.Flags.dup_fixed
~serialise:(fun alloc x ->
let a = alloc 1 in
Bigstring.set_uint8_exn a ~pos:0 x ;
a )
~deserialise:(Bigstring.get_uint8 ~pos:0)
()

let blake2 =
Lmdb.Conv.(
make
~serialise:(fun alloc x ->
let str = Blake2.to_raw_string x in
serialise string alloc str )
~deserialise:(fun s -> deserialise string s |> Blake2.of_raw_string)
())

let bin_prot_conv (t : 'a Bin_prot.Type_class.t) =
Lmdb.Conv.(
make ~flags:Lmdb.Conv.Flags.dup_fixed
~serialise:(fun alloc x ->
let sz = t.writer.size x in
let res = alloc sz in
let _pos = t.writer.write ~pos:0 res in
res )
~deserialise:
(let pos_ref = ref 0 in
t.reader.read ~pos_ref )
())
15 changes: 15 additions & 0 deletions src/lib/lmdb_storage/dune
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
(library
(name lmdb_storage)
(public_name lmdb_storage)
(libraries
;; opam libraries
lmdb
;; local libraries
file_system
blake2
;; test deps
inline_test_quiet_logs
)
(inline_tests (flags -verbose -show-counts))
(instrumentation (backend bisect_ppx))
(preprocess (pps ppx_mina ppx_version ppx_jane ppx_deriving.std ppx_let ppx_deriving_yojson)))
Loading