this repo has no description
2
fork

Configure Feed

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

Add reverse iteration to btree iterator

garrison af49e5e4 97d1e6f5

+89 -8
+3 -3
lib/btree/fuzz/model_fuzz.ex
··· 91 91 92 92 start_key = make_key(opt_key_bits) 93 93 count = Enum.random(1..10) 94 - reverse? = false 95 - #dbg {start_key, count} 94 + reverse? = Enum.random([true, false]) 95 + #dbg {start_key, count, reverse?} 96 96 #dbg SimpleKV.dump(simple_kv), limit: :infinity 97 97 98 98 btree_pairs = scan(btree, start_key, count, reverse?) 99 - skv_pairs = SimpleKV.scan(simple_kv, start_key, count) 99 + skv_pairs = SimpleKV.scan(simple_kv, start_key, count, reverse?) 100 100 assert btree_pairs == skv_pairs 101 101 102 102 state
+10 -3
lib/btree/fuzz/simple_kv.ex
··· 15 15 end) 16 16 end 17 17 18 - @spec scan(t, binary, non_neg_integer) :: [{binary, binary}] 19 - def scan(simple_kv, start_key, count) do 18 + @spec scan(t, binary, non_neg_integer, boolean) :: [{binary, binary}] 19 + def scan(simple_kv, start_key, count, _reverse? = true) do 20 + simple_kv 21 + |> Enum.sort_by(fn {k, _v} -> k end, :desc) 22 + |> Enum.filter(fn {k, _v} -> k < start_key end) 23 + |> Enum.take(count) 24 + end 25 + 26 + def scan(simple_kv, start_key, count, _reverse? = false) do 20 27 simple_kv 21 - |> Enum.sort_by(fn {k, _v} -> k end) 28 + |> Enum.sort_by(fn {k, _v} -> k end, :asc) 22 29 |> Enum.filter(fn {k, _v} -> k >= start_key end) 23 30 |> Enum.take(count) 24 31 end
+76 -2
lib/btree/iterator.ex
··· 27 27 [{:root_address, {root_index, root_checksum}}] = :ets.lookup(root_store, :root_address) 28 28 root_data = BTree.read_page(page_store, root_index, root_checksum) 29 29 30 - iterator = %Iterator{ 30 + it = %Iterator{ 31 31 btree: btree, 32 32 page_stack: [], 33 33 current_page: root_data, ··· 35 35 current_pair: nil, 36 36 reverse?: reverse?, 37 37 } 38 - seek_forward(iterator, start_key) 38 + 39 + case reverse? do 40 + true -> seek_backward(it, start_key) 41 + false -> seek_forward(it, start_key) 42 + end 39 43 end 40 44 41 45 @spec next(t) :: t 42 46 def next(%Iterator{reverse?: false} = it), do: next_forward(it) 47 + def next(%Iterator{reverse?: true} = it), do: next_backward(it) 48 + 49 + defp seek_backward(%Iterator{} = it, search_key) do 50 + it = seek(it, search_key) 51 + {key, _value} = it.current_pair 52 + 53 + case key >= search_key do 54 + true -> next_backward(it) 55 + false -> it 56 + end 57 + end 43 58 44 59 defp seek_forward(%Iterator{} = it, search_key) do 45 60 it = seek(it, search_key) ··· 166 181 case (key >= search_key) or (i == (pair_count - 1)) do 167 182 true -> {i, {key, value}} 168 183 false -> do_seek_leaf(page_data, slots_start, pair_count, search_key, i + 1) 184 + end 185 + end 186 + 187 + defp next_backward(%Iterator{} = it) do 188 + %{ 189 + current_page: current_page, 190 + current_i: current_i, 191 + } = it 192 + << 193 + _::binary-size(byte_size(current_page) - c_page_trailer_bytes()), 194 + # TODO: cache these in the iterator 195 + pair_count::integer-16, 196 + type_byte::integer-8, 197 + >> = current_page 198 + 199 + case current_i > 0 do 200 + true -> 201 + current_i = current_i - 1 202 + case type_byte do 203 + 0x00 -> 204 + child_page = inner_child_page_at(it.btree.page_store, current_page, pair_count, current_i) 205 + << 206 + _::binary-size(byte_size(current_page) - c_page_trailer_bytes()), 207 + child_pair_count::integer-16, 208 + _type_byte::integer-8, 209 + >> = current_page 210 + 211 + it = %{it | 212 + page_stack: [{current_i, current_page} | it.page_stack], 213 + current_page: child_page, 214 + current_i: child_pair_count, 215 + current_pair: nil, 216 + } 217 + next_forward(it) 218 + 219 + 0x01 -> 220 + current_pair = leaf_pair_at(current_page, pair_count, current_i) 221 + 222 + %{it | 223 + current_i: current_i, 224 + current_pair: current_pair, 225 + } 226 + end 227 + 228 + false -> 229 + case it.page_stack do 230 + [] -> 231 + %{it | 232 + current_pair: :infinity, 233 + } 234 + 235 + [{page, i} | stack_rest] -> 236 + it = %{it | 237 + page_stack: stack_rest, 238 + current_page: page, 239 + current_i: i, 240 + } 241 + next_forward(it) 242 + end 169 243 end 170 244 end 171 245