this repo has no description
2
fork

Configure Feed

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

Split root recursively as needed

garrison 8bc5f691 b2897481

+40 -3
+39 -2
lib/btree/writer.ex
··· 2 2 alias Hobbes.BTree 3 3 alias Hobbes.BTree.{FreeList, Page} 4 4 5 + import ExUnit.Assertions, only: [assert: 1] 6 + 7 + @keyspace_start_key "" 8 + @keyspace_end_key "\xFF\xFF\xFF\xFF" 9 + 5 10 @spec apply_batch(BTree.t, list) :: :ok 6 11 def apply_batch(%BTree{} = btree, mutations) do 7 12 %{ ··· 13 18 14 19 [{:root_address, {root_index, root_checksum}}] = :ets.lookup(root_store, :root_address) 15 20 16 - [{_, <<new_ri::integer-64, new_rch::binary-16>>}] = do_flush(btree, root_index, root_checksum, "", "\xFF\xFF\xFF\xFF") 21 + {new_root_index, new_root_checksum} = flush_tree(btree, root_index, root_checksum) 17 22 18 - :ets.insert(root_store, {:root_address, {new_ri, new_rch}}) 23 + :ets.insert(root_store, {:root_address, {new_root_index, new_root_checksum}}) 19 24 :ok 20 25 end 21 26 ··· 26 31 {:clear, k} -> :ets.insert(write_buffer, {k, :tombstone}) 27 32 end 28 33 do_write_buffer(mutations_rest, write_buffer) 34 + end 35 + 36 + defp flush_tree(%BTree{} = btree, root_index, root_checksum) do 37 + root_addresses = do_flush(btree, root_index, root_checksum, @keyspace_start_key, @keyspace_end_key) 38 + maybe_split_root(btree, root_addresses) 39 + end 40 + 41 + defp maybe_split_root(%BTree{} = btree, root_addresses) do 42 + case root_addresses do 43 + [{_ek, address}] -> 44 + <<root_index::integer-64, root_checksum::binary-16>> = address 45 + {root_index, root_checksum} 46 + 47 + pairs -> 48 + assert root_addresses != [] 49 + 50 + new_root_data = Page.encode_page_from_pairs(:leaf, btree.opts.page_size, pairs, @keyspace_end_key) 51 + new_indices = FreeList.reserve_pages(btree.free_list, length(new_root_data)) 52 + 53 + new_root_addresses = 54 + Enum.zip(new_root_data, new_indices) 55 + |> Enum.map(fn {{ek, data}, index} -> 56 + :ok = BTree.write_page(btree.page_store, index, data) 57 + 58 + checksum = BTree.checksum(data) 59 + {ek, <<index::integer-64, checksum::binary-16>>} 60 + end) 61 + 62 + # We check if the root needs to be split again 63 + # TODO: ensure this is fuzzed as it will be rare in practice 64 + maybe_split_root(btree, new_root_addresses) 65 + end 29 66 end 30 67 31 68 defp do_flush(%BTree{} = btree, page_index, page_checksum, page_sk, page_ek) do
+1 -1
test/btree_test.exs
··· 21 21 {:write, "f", "6"}, 22 22 ]) 23 23 24 - mutations = Enum.map(1..300, fn i -> 24 + mutations = Enum.map(1..3000, fn i -> 25 25 str = Integer.to_string(i) 26 26 {:write, str, String.reverse(str)} 27 27 end)