this repo has no description
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add writer for new inner page format

garrison 1347ef11 de5933d6

+123
+2
lib/btree/utils.ex
··· 5 5 defmacro c_page_pair_overhead_bytes, do: 2 + 2 6 6 # pair_offset 7 7 defmacro c_page_slot_entry_bytes, do: 2 8 + # index + checksum 9 + defmacro c_inner_pointer_bytes, do: 8 + 16 8 10 end
+121
lib/btree/writer.ex
··· 3 3 alias Hobbes.BTree.{FreeList, Page} 4 4 5 5 import ExUnit.Assertions, only: [assert: 1] 6 + import Hobbes.BTree.Utils 6 7 7 8 @keyspace_start_key "" 8 9 @keyspace_end_key "\xFF\xFF\xFF\xFF" ··· 122 123 123 124 _ -> pairs_acc 124 125 end 126 + end 127 + 128 + defp write_inner(%BTree{} = btree, end_key, pairs) do 129 + %{ 130 + opts: %{ 131 + page_size: opt_page_size, 132 + }, 133 + } = btree 134 + 135 + {keys_data, pointers_data, offsets, count} = do_write_inner(pairs, "", "", [], 0) 136 + maybe_split_inner(opt_page_size, end_key, keys_data, pointers_data, offsets, count) 137 + end 138 + 139 + # Have (p = pointer, k = key) 140 + # p - k - p - k - p - k - p 141 + # 142 + # Want 143 + # k 144 + # / \ 145 + # p - k - p p - k - p 146 + # 147 + # 0 1 2 148 + # k k k 149 + # p p p p 150 + defp maybe_split_inner(opt_page_size, end_key, keys_data, pointers_data, offsets, pointer_count) do 151 + key_count = pointer_count - 1 152 + data_size = byte_size(keys_data) + byte_size(pointers_data) + (key_count * c_page_slot_entry_bytes()) + c_page_trailer_bytes() 153 + 154 + case data_size <= opt_page_size do 155 + true -> 156 + pad_bytes = opt_page_size - data_size 157 + assert pad_bytes >= 0 158 + 159 + slots_data = encode_slots(offsets, "") 160 + type_byte = 0x00 161 + 162 + page = << 163 + keys_data::binary, 164 + 0::integer-unit(8)-size(pad_bytes), 165 + pointers_data::binary, 166 + slots_data::binary, 167 + pointer_count::integer-16, 168 + type_byte::integer-8, 169 + >> 170 + [{end_key, page}] 171 + 172 + false -> 173 + assert key_count >= 3 174 + midpoint_i = div(key_count, 2) 175 + 176 + {offsets1, offsets2} = Enum.split(offsets, midpoint_i) 177 + [offset_mid | offsets2] = offsets2 178 + assert offsets2 != [] 179 + 180 + << 181 + keys_data1::binary-size(offset_mid), 182 + mid_key_size::integer-16, 183 + mid_key::binary-size(mid_key_size), 184 + keys_data2::binary, 185 + >> = keys_data 186 + 187 + pointer_count1 = midpoint_i + 1 188 + pointer_count2 = pointer_count - pointer_count1 189 + << 190 + pointers_data1::binary-size(pointer_count1 * c_inner_pointer_bytes()), 191 + pointers_data2::binary, 192 + >> = pointers_data 193 + 194 + end_key1 = mid_key 195 + end_key2 = end_key 196 + 197 + pages1 = maybe_split_inner(opt_page_size, end_key1, keys_data1, pointers_data1, offsets1, pointer_count1) 198 + pages2 = maybe_split_inner(opt_page_size, end_key2, keys_data2, pointers_data2, offsets2, pointer_count2) 199 + pages1 ++ pages2 200 + end 201 + end 202 + 203 + defp do_write_inner([{_end_key, pointer}], keys_acc, pointers_acc, offsets_acc, count_acc) do 204 + #assert end_key == nil 205 + 206 + assert byte_size(pointer) == 24 207 + pointers_acc = << 208 + pointers_acc::binary, 209 + pointer::binary, 210 + >> 211 + 212 + count_acc = count_acc + 1 213 + {keys_acc, pointers_acc, Enum.reverse(offsets_acc), count_acc} 214 + end 215 + 216 + defp do_write_inner([{key, pointer} | pairs_rest], keys_acc, pointers_acc, offsets_acc, count_acc) do 217 + offset = byte_size(keys_acc) 218 + key_size = byte_size(key) 219 + 220 + keys_acc = << 221 + keys_acc::binary, 222 + key_size::integer-16, 223 + key::binary, 224 + >> 225 + 226 + assert byte_size(pointer) == 24 227 + pointers_acc = << 228 + pointers_acc::binary, 229 + pointer::binary, 230 + >> 231 + 232 + offsets_acc = [offset | offsets_acc] 233 + count_acc = count_acc + 1 234 + do_write_inner(pairs_rest, keys_acc, pointers_acc, offsets_acc, count_acc) 235 + end 236 + 237 + defp encode_slots([], slots_acc), do: slots_acc 238 + defp encode_slots([offset | offsets_rest], slots_acc) do 239 + assert offset < (2 ** 16) 240 + # See constant: c_page_slot_entry_bytes() 241 + slots_acc = << 242 + slots_acc::binary, 243 + offset::integer-16, 244 + >> 245 + encode_slots(offsets_rest, slots_acc) 125 246 end 126 247 end