this repo has no description
2
fork

Configure Feed

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

Split page recursively if it exceeds the page size

garrison b2897481 03952cda

+64 -12
+4 -2
lib/btree/btree.ex
··· 54 54 btree 55 55 end 56 56 57 + @keyspace_end_key "\xFF\xFF\xFF\xFF" 58 + 57 59 defp create_root_pages(%BTree{} = btree) do 58 60 %{ 59 61 free_list: free_list, ··· 68 70 69 71 [root_index, leaf_index] = FreeList.reserve_pages(free_list, 2) 70 72 71 - [leaf_data] = Page.encode_page_from_pairs(:leaf, opt_page_size, []) 73 + [{_ek, leaf_data}] = Page.encode_page_from_pairs(:leaf, opt_page_size, [], @keyspace_end_key) 72 74 leaf_checksum = checksum(leaf_data) 73 75 :ok = write_page(page_store, leaf_index, leaf_data) 74 76 ··· 76 78 leaf_address = <<leaf_index::integer-64, leaf_checksum::binary-16>> 77 79 78 80 root_pairs = [{leaf_end_key, leaf_address}] 79 - [root_data] = Page.encode_page_from_pairs(:inner, opt_page_size, root_pairs) 81 + [{_ek, root_data}] = Page.encode_page_from_pairs(:inner, opt_page_size, root_pairs, @keyspace_end_key) 80 82 root_checksum = checksum(root_data) 81 83 :ok = write_page(page_store, root_index, root_data) 82 84
+45 -5
lib/btree/page.ex
··· 10 10 defp decode_type(0x00), do: :inner 11 11 defp decode_type(0x01), do: :leaf 12 12 13 - def encode_page_from_pairs(page_type, opt_page_size, pairs) do 13 + def encode_page_from_pairs(page_type, opt_page_size, pairs, end_key) do 14 14 type_byte = encode_type(page_type) 15 15 {body, offsets, pair_count} = do_encode_page(pairs, "", [], 0) 16 16 17 - maybe_split(opt_page_size, type_byte, body, offsets, pair_count) 17 + maybe_split(opt_page_size, type_byte, end_key, body, offsets, pair_count) 18 18 end 19 19 20 - defp maybe_split(opt_page_size, type_byte, body, offsets, pair_count) do 20 + defp maybe_split(opt_page_size, type_byte, end_key, body, offsets, pair_count) do 21 21 data_size = byte_size(body) + (pair_count * c_page_slot_entry_bytes()) + c_page_trailer_bytes() 22 22 23 23 case data_size > opt_page_size do 24 24 true -> 25 - assert false 25 + target_midpoint_bytes = div(data_size, 2) 26 + assert target_midpoint_bytes > c_page_trailer_bytes() 27 + 28 + midpoint_i = find_midpoint(offsets, target_midpoint_bytes, 0) 29 + {offsets1, offsets2} = Enum.split(offsets, midpoint_i) 30 + 31 + # TODO: is this possible? 32 + assert offsets2 != [] 33 + body2_offset = hd(offsets2) 34 + offsets2 = Enum.map(offsets2, fn o -> o - body2_offset end) 35 + 36 + << 37 + body1::binary-size(body2_offset), 38 + body2::binary, 39 + >> = body 40 + 41 + << 42 + key_size::integer-16, 43 + _value_size::integer-16, 44 + end_key1::binary-size(key_size), 45 + _rest::binary, 46 + >> = body2 47 + end_key2 = end_key 48 + 49 + pair_count1 = midpoint_i 50 + pair_count2 = pair_count - pair_count1 51 + 52 + pages1 = maybe_split(opt_page_size, type_byte, end_key1, body1, offsets1, pair_count1) 53 + pages2 = maybe_split(opt_page_size, type_byte, end_key2, body2, offsets2, pair_count2) 54 + pages1 ++ pages2 26 55 27 56 false -> 28 57 pad_bytes = opt_page_size - data_size ··· 42 71 type_byte::integer-8, 43 72 >> 44 73 45 - [page_data] 74 + [{end_key, page_data}] 75 + end 76 + end 77 + 78 + defp find_midpoint([offset | offsets_rest], target, i) do 79 + size = offset + (c_page_slot_entry_bytes() * i) + c_page_trailer_bytes() 80 + case size > target do 81 + true -> 82 + assert i > 0 83 + i 84 + false -> 85 + find_midpoint(offsets_rest, target, i + 1) 46 86 end 47 87 end 48 88
+9 -5
lib/btree/writer.ex
··· 39 39 :leaf -> fill_leaf(btree.write_buffer, page_ek, pairs) 40 40 end 41 41 42 - [new_page_data] = Page.encode_page_from_pairs(page_type, btree.opts.page_size, pairs) 43 - [new_page_index] = FreeList.reserve_pages(btree.free_list, 1) 44 - new_page_checksum = BTree.checksum(new_page_data) 45 - :ok = BTree.write_page(btree.page_store, new_page_index, new_page_data) 42 + new_encoded_pages = Page.encode_page_from_pairs(page_type, btree.opts.page_size, pairs, page_ek) 43 + new_indices = FreeList.reserve_pages(btree.free_list, length(new_encoded_pages)) 46 44 47 - [{page_ek, <<new_page_index::integer-64, new_page_checksum::binary-16>>}] 45 + Enum.zip(new_encoded_pages, new_indices) 46 + |> Enum.map(fn {{ek, data}, index} -> 47 + :ok = BTree.write_page(btree.page_store, index, data) 48 + 49 + checksum = BTree.checksum(data) 50 + {ek, <<index::integer-64, checksum::binary-16>>} 51 + end) 48 52 end 49 53 50 54 defp fill_inner(%BTree{} = btree, pairs, page_sk, page_ek, writes_acc) do
+6
test/btree_test.exs
··· 20 20 {:write, "e", "5"}, 21 21 {:write, "f", "6"}, 22 22 ]) 23 + 24 + mutations = Enum.map(1..300, fn i -> 25 + str = Integer.to_string(i) 26 + {:write, str, String.reverse(str)} 27 + end) 28 + :ok = BTree.Writer.apply_batch(btree, mutations) 23 29 end 24 30 end 25 31 end