this repo has no description
2
fork

Configure Feed

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

Add BTree.Store and BTree.BlockDevice

garrison b8c1ad5c 66c99ccd

+143 -1
+117
lib/btree/block_device.ex
··· 1 + defmodule Hobbes.BTree.BlockDevice do 2 + import ExUnit.Assertions, only: [assert: 1] 3 + 4 + @type t :: tuple 5 + 6 + @spec new(pos_integer) :: t 7 + def new(block_size) do 8 + table = :ets.new(__MODULE__, [:ordered_set, :protected]) 9 + {:block_device, block_size, table} 10 + end 11 + 12 + @spec read(t, non_neg_integer, non_neg_integer) :: binary 13 + def read({:block_device, opt_block_size, _table} = bd, pos, bytes) do 14 + # TODO 15 + assert rem(pos, opt_block_size) == 0 16 + assert bytes == opt_block_size 17 + 18 + block_index = div(pos, opt_block_size) 19 + get(bd, block_index) 20 + end 21 + 22 + @spec write(t, non_neg_integer, binary) :: :ok 23 + def write({:block_device, opt_block_size, table} = bd, pos, bin) do 24 + bin_size = byte_size(bin) 25 + 26 + block_index = div(pos, opt_block_size) 27 + start_offset = rem(pos, opt_block_size) 28 + end_offset = start_offset + bin_size 29 + 30 + case end_offset <= opt_block_size do 31 + true -> 32 + old_block = get(bd, block_index) 33 + 34 + << 35 + prefix::binary-size(start_offset), 36 + _middle::binary-size(end_offset), 37 + suffix::binary, 38 + >> = old_block 39 + 40 + new_block = << 41 + prefix::binary, 42 + bin::binary, 43 + suffix::binary, 44 + >> 45 + assert byte_size(new_block) == opt_block_size 46 + 47 + put(table, block_index, new_block) 48 + 49 + false -> 50 + old_block = get(bd, block_index) 51 + 52 + << 53 + prefix::binary-size(start_offset), 54 + _rest::binary, 55 + >> = old_block 56 + 57 + << 58 + bin_part::binary-size(opt_block_size - start_offset), 59 + bin_rest::binary, 60 + >> = bin 61 + 62 + new_block = << 63 + prefix::binary, 64 + bin_part::binary, 65 + >> 66 + assert byte_size(new_block) == opt_block_size 67 + 68 + do_write_blocks(bin_rest, bd, table, opt_block_size, block_index + 1) 69 + end 70 + :ok 71 + end 72 + 73 + defp do_write_blocks("", _bd, _table, _opt_block_size, _block_index_acc) do 74 + :ok 75 + end 76 + 77 + defp do_write_blocks(bin, bd, table, opt_block_size, block_index_acc) when byte_size(bin) < opt_block_size do 78 + old_block = get(bd, block_index_acc) 79 + 80 + << 81 + _::binary-size(byte_size(bin)), 82 + suffix::binary, 83 + >> = old_block 84 + 85 + new_block = << 86 + bin::binary, 87 + suffix::binary, 88 + >> 89 + 90 + put(table, block_index_acc, new_block) 91 + :ok 92 + end 93 + 94 + defp do_write_blocks(bin, bd, table, opt_block_size, block_index_acc) do 95 + << 96 + bin_part::binary-size(opt_block_size), 97 + bin_rest::binary, 98 + >> = bin 99 + bin_part = :binary.copy(bin_part) 100 + 101 + put(table, block_index_acc, bin_part) 102 + 103 + block_index_acc = block_index_acc + 1 104 + do_write_blocks(bin_rest, bd, table, opt_block_size, block_index_acc) 105 + end 106 + 107 + defp get({:block_device, opt_block_size, table}, block_index) do 108 + case :ets.lookup(table, block_index) do 109 + [{_block_index, data}] -> data 110 + [] -> <<0::integer-unit(8)-size(opt_block_size)>> 111 + end 112 + end 113 + 114 + defp put(table, block_index, data) do 115 + :ets.insert(table, {block_index, data}) 116 + end 117 + end
+5 -1
lib/btree/btree.ex
··· 1 1 defmodule Hobbes.BTree do 2 2 alias Hobbes.BTree 3 - alias Hobbes.BTree.{FreeList, Page, Writer} 3 + alias Hobbes.BTree.{Store, FreeList, Page, Writer} 4 4 5 5 import ExUnit.Assertions, only: [assert: 1] 6 6 ··· 16 16 17 17 @type t :: %__MODULE__{ 18 18 opts: Opts.t, 19 + store: :ets.table, 19 20 page_store: :ets.table, 20 21 free_list: FreeList.t, 21 22 root_store: :ets.table, ··· 29 30 } 30 31 @enforce_keys [ 31 32 :opts, 33 + :store, 32 34 :page_store, 33 35 :free_list, 34 36 :root_store, ··· 52 54 end 53 55 54 56 def new(opts \\ []) do 57 + path = Keyword.get(opts, :path, :memory) 55 58 opts = parse_opts(opts) 56 59 57 60 btree = %BTree{ 58 61 opts: opts, 62 + store: Store.new(path, opts.page_size), 59 63 page_store: :ets.new(__MODULE__, [:set, :protected]), 60 64 free_list: FreeList.new(), 61 65 root_store: :ets.new(__MODULE__, [:ordered_set, :protected]),
+21
lib/btree/store.ex
··· 1 + defmodule Hobbes.BTree.Store do 2 + alias Hobbes.BTree.BlockDevice 3 + 4 + import ExUnit.Assertions, only: [assert: 1] 5 + 6 + @type t :: BlockDevice.t 7 + 8 + @spec new(String.t | :memory, pos_integer) :: t 9 + def new(path, block_size) do 10 + case path do 11 + :memory -> BlockDevice.new(block_size) 12 + end 13 + end 14 + 15 + @spec write_page(t, non_neg_integer, binary) :: :ok 16 + def write_page({:block_device, opt_block_size, _} = bd, page_index, page_data) do 17 + assert byte_size(page_data) == opt_block_size 18 + 19 + :ok = BlockDevice.write(bd, page_index * opt_block_size, page_data) 20 + end 21 + end