|
| 1 | +[@@@warning "-69"] |
| 2 | + |
| 3 | +(* minimal B+ tree struct *) |
| 4 | +type t = { |
| 5 | + storage_m : Storage_manager.t; (* file used to store to disk *) |
| 6 | + key : Keys.t; |
| 7 | + mutable root : Nodes.t; |
| 8 | + mutable root_num : int; |
| 9 | +} |
| 10 | + |
| 11 | +[@@@warning "+69"] |
| 12 | + |
| 13 | +let serialize (node : Nodes.t) (block_size : int) : Page.Page.t = |
| 14 | + (* recursive iterative helpers*) |
| 15 | + let rec layout_keys (nd : Nodes.t) (pg : Page.Page.t) pair_size i : unit = |
| 16 | + if i >= nd.capacity then |
| 17 | + () |
| 18 | + else |
| 19 | + let key_offset = 12 + (i * pair_size) + 4 in |
| 20 | + begin match nd.keys.(i) with |
| 21 | + | Integer n -> Page.Page.set_int32 pg key_offset n |
| 22 | + | Varchar s -> Page.Page.set_string_raw pg key_offset s |
| 23 | + end; |
| 24 | + layout_keys nd pg pair_size (i + 1) |
| 25 | + in |
| 26 | + |
| 27 | + let rec layout_pointers (nd : Nodes.t) (pg : Page.Page.t) pair_size i : unit = |
| 28 | + if i > nd.capacity then |
| 29 | + () |
| 30 | + else |
| 31 | + let pointer_offset = 12 + (i * pair_size) in |
| 32 | + Page.Page.set_int32 pg pointer_offset (Int32.of_int nd.pointers.(i)); |
| 33 | + layout_pointers nd pg pair_size (i + 1) |
| 34 | + in |
| 35 | + |
| 36 | + (* Acutal serialization below*) |
| 37 | + let page = Page.Page.make ~block_size in |
| 38 | + (* set node type at first 4 bytes *) |
| 39 | + Page.Page.set_int32 page 0 (Nodes.serialize_node node.node_t); |
| 40 | + (* Set parent offset at 4 *) |
| 41 | + Page.Page.set_int32 page 4 (Int32.of_int node.parent); |
| 42 | + (* set curr size at 8 *) |
| 43 | + Page.Page.set_int32 page 8 (Int32.of_int node.cur_size); |
| 44 | + (* get the pointer -> key size, 4 bytes pointer + M bytes key*) |
| 45 | + let pair_size = 4 + Keys.size_of_key node.key_type in |
| 46 | + layout_keys node page pair_size 0; |
| 47 | + layout_pointers node page pair_size 0; |
| 48 | + |
| 49 | + let final_pointer_offset = 12 + (node.capacity * pair_size) in |
| 50 | + (* ensuring serializing the sibling pointer *) |
| 51 | + if node.node_t = Leaf then |
| 52 | + Page.Page.set_int32 page final_pointer_offset |
| 53 | + (Int32.of_int node.pointers.(node.capacity)); |
| 54 | + page |
| 55 | + |
| 56 | +let get_num_keys (block_size : int) (key_type : Keys.t) : int = |
| 57 | + (* 12 bytes needed for metadata + 4 bytes for final sib pointer*) |
| 58 | + (block_size - 16) / (4 + Keys.size_of_key key_type) |
| 59 | + |
| 60 | +let unused_pointer_serial = 3722304989 (*0xDDDDDDDD *) |
| 61 | + |
| 62 | +let deserialize (page : Page.Page.t) (key_type : Keys.t) (block_size : int) : |
| 63 | + Nodes.t = |
| 64 | + (* read node type *) |
| 65 | + let node_type = Nodes.int32_to_node_t (Page.Page.get_int32 page 0) in |
| 66 | + (* Read parent*) |
| 67 | + let parent = Int32.to_int (Page.Page.get_int32 page 4) in |
| 68 | + (* Read N the cur num of keys *) |
| 69 | + let cur_size = Int32.to_int (Page.Page.get_int32 page 8) in |
| 70 | + (* Get the capacity using block size and k type *) |
| 71 | + let capacity = get_num_keys block_size key_type in |
| 72 | + let keys = Array.init capacity (fun _ -> Keys.empty_key key_type) in |
| 73 | + let pointers = Array.init (capacity + 1) (fun _ -> unused_pointer_serial) in |
| 74 | + let pair_size = 4 + Keys.size_of_key key_type in |
| 75 | + |
| 76 | + (* reading keys and pointers - not doing this one recursively*) |
| 77 | + for i = 0 to cur_size - 1 do |
| 78 | + let pointer_offset = 12 + (i * pair_size) in |
| 79 | + let key_offset = 12 + (i * pair_size) + 4 in |
| 80 | + (* reading in the pointers from bytes *) |
| 81 | + pointers.(i) <- Int32.to_int (Page.Page.get_int32 page pointer_offset); |
| 82 | + (* reading the keys from bytes *) |
| 83 | + match key_type with |
| 84 | + | Keys.TVarchar n -> |
| 85 | + let str = Page.Page.get_string_raw page key_offset n in |
| 86 | + keys.(i) <- Keys.Varchar str |
| 87 | + | Keys.TInteger -> |
| 88 | + let num = Page.Page.get_int32 page key_offset in |
| 89 | + keys.(i) <- Keys.Integer num |
| 90 | + done; |
| 91 | + |
| 92 | + (* again final pointer read *) |
| 93 | + let last_pointer_offset = 12 + (cur_size * pair_size) in |
| 94 | + pointers.(cur_size) <- |
| 95 | + Int32.to_int (Page.Page.get_int32 page last_pointer_offset); |
| 96 | + (* sibling pointer is last pointer in array at index capacity *) |
| 97 | + let sib_pointer_offset = 12 + (capacity * pair_size) in |
| 98 | + if node_type = Leaf then |
| 99 | + pointers.(capacity) <- |
| 100 | + Int32.to_int (Page.Page.get_int32 page sib_pointer_offset); |
| 101 | + |
| 102 | + { node_t = node_type; parent; cur_size; keys; pointers; capacity; key_type } |
| 103 | + |
| 104 | +(* writing nodes to disk *) |
| 105 | +let write_node (btree : t) (node : Nodes.t) (n : int) : unit = |
| 106 | + let block_size = File_manager.get_blocksize btree.storage_m.file_manager in |
| 107 | + let page = serialize node block_size in |
| 108 | + Storage_manager.update_block_num ~storage_m:btree.storage_m ~block_num:n ~page |
| 109 | + |
| 110 | +let write_node_append (btree : t) (node : Nodes.t) : int = |
| 111 | + let block_size = File_manager.get_blocksize btree.storage_m.file_manager in |
| 112 | + let page = serialize node block_size in |
| 113 | + let block = Storage_manager.append ~storage_m:btree.storage_m ~page in |
| 114 | + Page.Block.block_num block |
| 115 | + |
| 116 | +(* getting a block from the btree and deserialize it into a node *) |
| 117 | +let get_node (btree : t) (p : int) : Nodes.t = |
| 118 | + let block_size = File_manager.get_blocksize btree.storage_m.file_manager in |
| 119 | + let page = |
| 120 | + Storage_manager.get_block ~storage_m:btree.storage_m ~block_num:p |
| 121 | + in |
| 122 | + deserialize page btree.key block_size |
0 commit comments