Storage Engine
Storage Engine
As I learn to implement a simple Database I post OCaml code to create Data Structures.
- The OCaml code is raw even though it compiles and simple tests pass. I look at other source code written in Haskell, Rust, SML etc. to understand the Data Structures.
- The code format and FP principles have to be reviewed and revised.
- Eventually I hope the toy Database will have SQL parsers and optimizers.
Log-Structured Merge
open Stdlib
let state = Random.State.make_self_init()
type 'v values = Int
type 'k keys = Int
type ('k, 'v) node =
| Empty
| Node of {
keys : 'k;
values : 'v;
sibling : ('k, 'v) node;
child : ('k, 'v) node;
}
| Head of
{ sibling : ('k, 'v) node;
child : ('k, 'v) node
}
type ( 'k, 'v) skip_list =
{ skpstate : Random.State.t; (*Seed *)
skpinternal : ('k, 'v) node }
let ltekey (node : ('k, 'v ) node) key : bool =
match node with
| Node {keys = k; _} -> k <= key
| Empty -> false
| _ -> true
let ltkey (node : ('k, 'v ) node) key : bool =
match node with
| Node {keys = k; _} -> k < key
| Empty -> false
| _ -> true
let eqkey (node : ('k, 'v ) node) key : bool =
match node with
| Node {keys = k; _} -> k == key
| _ -> false
let empty_check (skp : ('k, 'v) skip_list) : bool =
match skp.skpinternal with
| Head { sibling = Empty; child = Empty } -> true
| _ -> false
let create_empty_skiplist state : ('k, 'v) skip_list =
let head = Head { sibling = Empty; child = Empty } in
let st = state in
{ skpstate = st ; skpinternal = head }
let rec addlevels k v (internal, levels ): ('k, 'v ) node =
match levels with
| levels when levels > 0 -> create_level k v levels ( splitlevel internal)
| _ -> internal
and
create_level k v levels (l, r) =
match levels with
| 1 -> let node = Node { keys = k; values = v; sibling = Empty; child = r} in
Head { sibling = node ; child = r }
| _ ->
let head = Head { sibling = Empty; child = l } in
let head1 = Head { sibling = Empty; child = r } in
create_level k v (levels - 1) (head , head1)
and
splitlevel ( node : ('k, 'v) node ) : ('k, 'v) node * ('k, 'v) node =
match node with
| Head { sibling = _; child = _ } as head1 ->
let head = Head { sibling = Empty; child = head1 } in
(head, node)
| ns ->
let (next,r) = splitlevel ns in
(next , r)
let number (state : Random.State.t) =
let rec randomgen n (state : Random.State.t) =
let b = Random.State.bool state
in if b then randomgen (n + 1) state
else (n, state )
in randomgen 0 state
let rec insert k v (skp : ('k, 'v) skip_list ) =
let (rg, state') = number skp.skpstate in
let skplist = addlevels k v (create_skiplist k v rg skp.skpinternal) in
{ skpstate = state'; skpinternal = skplist }
and
create_skiplist k v rg (node : ('k, 'v) node) : ('k, 'v) node*int =
match node with
| Empty -> (Empty, rg)
| Head _ -> (Empty, rg)
| Node { keys = _; values = _; sibling = s; child = c } ->
if ( ltkey s k ) then
begin
match (create_skiplist k v rg s) with
| (a, _) ->
(Node { keys = k; values = v; sibling = a; child = c }, -1)
end
else if ( ltekey s k ) then
begin
let ns = Node { keys = k; values = v; sibling = s; child = c } in
(ns, -1)
end
else
begin
let (cn, w) = (create_skiplist k v rg c) in
if (w < 0) then
(Node { keys = k; values = v; sibling = s; child = cn }, -1)
else if w == 0 then
(Node { keys = k; values = v;
sibling = Node {keys = k; values = v;sibling = s; child = c}; child = cn }, -1)
else (Node {keys = k; values = v;
sibling = Head {sibling = s; child = cn}; child =c}, w - 1)
end
Written on June 1, 2024