diff options
Diffstat (limited to 'lib/bplustree.ml')
| -rw-r--r-- | lib/bplustree.ml | 245 |
1 files changed, 0 insertions, 245 deletions
diff --git a/lib/bplustree.ml b/lib/bplustree.ml deleted file mode 100644 index 608ff7e..0000000 --- a/lib/bplustree.ml +++ /dev/null @@ -1,245 +0,0 @@ -open Ctypes - -type tree_handle = unit - -module Key : sig - type t - - val size : int - val of_string : string -> t option - val to_string : t -> string -end = struct - type t = string - - let size = 32 - - let of_string value = - if String.length value = size then Some value else None - - let to_string key = key -end - -type t = { handle : tree_handle ptr; mutable closed : bool } - -type error = - | Not_found - | Invalid_argument - | Out_of_memory - | Io_error - | Corrupt_file - | Closed - | Unknown of int - -let tree_ptr = ptr void - -let status_ok = 0 - -let error_of_status = function - | 1 -> Not_found - | 2 -> Invalid_argument - | 3 -> Out_of_memory - | 4 -> Io_error - | 5 -> Corrupt_file - | status -> Unknown status - -let status_to_result = function - | status when status = status_ok -> Ok () - | status -> Error (error_of_status status) - -module Raw = struct - open Foreign - - let load_library () = - let default_names = - if Sys.win32 then - [ "sakura_shabptree.dll" ] - else if Sys.os_type = "Unix" then - [ "libsakura_shabptree.so" ] - else - [ "libsakura_shabptree.dylib" ] - in - let candidates = - match Sys.getenv_opt "SAKURA_BPLUSTREE_DLL" with - | Some filename -> filename :: default_names - | None -> default_names - in - let rec try_load = function - | [] -> None - | filename :: rest -> - (try Some (Dl.dlopen ~filename ~flags:[ Dl.RTLD_NOW ]) with - | Dl.DL_error _ -> try_load rest) - in - try_load candidates - - let library = lazy (load_library ()) - - let bind name signature = - match Lazy.force library with - | Some library -> foreign ~from:library name signature - | None -> foreign name signature - - let create = bind "sakura_bptree_create" (void @-> returning tree_ptr) - let free = bind "sakura_bptree_free" (tree_ptr @-> returning void) - let len = bind "sakura_bptree_len" (tree_ptr @-> returning uint64_t) - - let put = - bind "sakura_bptree_put" - (tree_ptr @-> ptr uint8_t @-> ptr void @-> uint64_t @-> returning int) - - let get = - bind "sakura_bptree_get" - (tree_ptr @-> ptr uint8_t @-> ptr (ptr void) @-> ptr uint64_t @-> returning int) - - let remove = - bind "sakura_bptree_remove" (tree_ptr @-> ptr uint8_t @-> returning int) - - let save = bind "sakura_bptree_save" (tree_ptr @-> string @-> returning int) - let load = bind "sakura_bptree_load" (string @-> ptr tree_ptr @-> returning int) - - let serialize = - bind "sakura_bptree_serialize" - (tree_ptr @-> ptr (ptr uint8_t) @-> ptr uint64_t @-> returning int) - - let deserialize = - bind "sakura_bptree_deserialize" - (ptr uint8_t @-> uint64_t @-> ptr tree_ptr @-> returning int) - - let free_buf = bind "free" (ptr uint8_t @-> returning void) - - let status_string = - bind "sakura_bptree_status_string" (int @-> returning string) -end - -let uint8_array_of_string value = - let len = String.length value in - let array = CArray.make uint8_t len in - for i = 0 to len - 1 do - CArray.set array i (Unsigned.UInt8.of_int (Char.code value.[i])) - done; - array - -let with_key_ptr key f = - let c_key = uint8_array_of_string (Key.to_string key) in - f (CArray.start c_key) - -let with_value_ptr value f = - let len = String.length value in - if len = 0 then f null 0 - else - let c_value = uint8_array_of_string value in - f (to_voidp (CArray.start c_value)) len - -let handle tree = - if tree.closed then Error Closed else Ok tree.handle - -let free tree = - if not tree.closed then begin - Raw.free tree.handle; - tree.closed <- true - end - -let close tree = - free tree; - Ok () - -let create () = - let handle = Raw.create () in - if is_null handle then Error Out_of_memory - else - let tree = { handle; closed = false } in - Gc.finalise free tree; - Ok tree - -let length tree = - match handle tree with - | Error error -> Error error - | Ok handle -> Ok (Unsigned.UInt64.to_int (Raw.len handle)) - -let put tree key value = - match handle tree with - | Error error -> Error error - | Ok handle -> - with_key_ptr key @@ fun key_ptr -> - with_value_ptr value @@ fun value_ptr value_len -> - Raw.put handle key_ptr value_ptr (Unsigned.UInt64.of_int value_len) - |> status_to_result - -let get tree key = - match handle tree with - | Error error -> Error error - | Ok handle -> - with_key_ptr key @@ fun key_ptr -> - let value_ptr = allocate (ptr void) null in - let len_ptr = allocate uint64_t Unsigned.UInt64.zero in - match Raw.get handle key_ptr value_ptr len_ptr |> status_to_result with - | Error error -> Error error - | Ok () -> - let len = Unsigned.UInt64.to_int !@len_ptr in - let value = from_voidp uint8_t !@value_ptr in - Ok (String.init len (fun i -> Char.chr (Unsigned.UInt8.to_int !@(value +@ i)))) - -let remove tree key = - match handle tree with - | Error error -> Error error - | Ok handle -> - with_key_ptr key @@ fun key_ptr -> Raw.remove handle key_ptr |> status_to_result - -let save tree path = - match handle tree with - | Error error -> Error error - | Ok handle -> Raw.save handle path |> status_to_result - -let load path = - let out = allocate tree_ptr null in - match Raw.load path out |> status_to_result with - | Ok () -> - let tree = { handle = !@out; closed = false } in - Gc.finalise free tree; - Ok tree - | Error error -> Error error - -let serialize tree = - match handle tree with - | Error error -> Error error - | Ok handle -> - let out_ptr = allocate (ptr uint8_t) (from_voidp uint8_t null) in - let out_len = allocate uint64_t Unsigned.UInt64.zero in - (match Raw.serialize handle out_ptr out_len |> status_to_result with - | Error error -> Error error - | Ok () -> - let len = Unsigned.UInt64.to_int !@out_len in - let p = !@out_ptr in - let bytes = Bytes.init len (fun i -> Char.chr (Unsigned.UInt8.to_int !@(p +@ i))) in - Raw.free_buf p; - Ok (Bytes.to_string bytes)) - -let deserialize data = - let len = String.length data in - let c_data = uint8_array_of_string data in - let out = allocate tree_ptr null in - match - Raw.deserialize (CArray.start c_data) (Unsigned.UInt64.of_int len) out - |> status_to_result - with - | Error error -> Error error - | Ok () -> - let tree = { handle = !@out; closed = false } in - Gc.finalise free tree; - Ok tree - -let error_message error = - match error with - | Closed -> "tree is closed" - | Unknown status -> Raw.status_string status - | _ -> - let status = - match error with - | Not_found -> 1 - | Invalid_argument -> 2 - | Out_of_memory -> 3 - | Io_error -> 4 - | Corrupt_file -> 5 - | Closed -> 2 - | Unknown status -> status - in - Raw.status_string status |
