Commit aef96be4735b5cf5f6067b916ba0a74a83ca6ca1
- Diff rendering mode:
- inline
- side by side
lib/strokedb/volumes.rb
(1 / 1)
|   | |||
| 2 | 2 | require 'volumes/block_volume' | |
| 3 | 3 | require 'volumes/distributed_pointer' | |
| 4 | 4 | require 'volumes/map_volume' | |
| 5 | require 'volumes/skiplist_volume' | ||
| 5 | require 'volumes/fixed_length_skiplist_volume' |
|   | |||
| 1 | module StrokeDB | ||
| 2 | class FixedLengthSkiplistVolume < SimpleSkiplist | ||
| 3 | |||
| 4 | def initialize(options = {}) | ||
| 5 | @options = options.stringify_keys | ||
| 6 | @volume = MapVolume.new(:record_size => (@options['maxlevel']||DEFAULT_MAXLEVEL) * 4 + 1 + | ||
| 7 | @options['key_length'] + @options['value_length'], :path => @options['path']) | ||
| 8 | @nodes = {} | ||
| 9 | super(nil,:maxlevel => @options['maxlevel'], :probability => @options['probability']) | ||
| 10 | end | ||
| 11 | |||
| 12 | def key_length | ||
| 13 | @options['key_length'] | ||
| 14 | end | ||
| 15 | |||
| 16 | def value_length | ||
| 17 | @options['value_length'] | ||
| 18 | end | ||
| 19 | |||
| 20 | def path | ||
| 21 | @options['path'] | ||
| 22 | end | ||
| 23 | |||
| 24 | def close! | ||
| 25 | @volume.close! | ||
| 26 | end | ||
| 27 | |||
| 28 | def inspect | ||
| 29 | "#<StrokeDB::FixedLengthSkiplistVolume:0x#{object_id.to_s(16)} path: #{path} key_length: #{key_length} value_length: #{value_length}" | ||
| 30 | end | ||
| 31 | |||
| 32 | private | ||
| 33 | |||
| 34 | # SimpleSkiplist overrides | ||
| 35 | |||
| 36 | |||
| 37 | def node_next(x, level) | ||
| 38 | if node = x[0][level] | ||
| 39 | read_node(node[-1]) | ||
| 40 | else | ||
| 41 | nil | ||
| 42 | end | ||
| 43 | end | ||
| 44 | |||
| 45 | def node_set_value!(x, value) | ||
| 46 | x[-2] = value | ||
| 47 | save_node!(x) | ||
| 48 | end | ||
| 49 | |||
| 50 | def node_insert_after!(x, prev, level) | ||
| 51 | x[0][level] = prev[0][level] | ||
| 52 | prev[0][level] = save_node!(x) | ||
| 53 | save_node!(prev) | ||
| 54 | end | ||
| 55 | |||
| 56 | def new_node(level, key, value, __pos = -1) | ||
| 57 | [ | ||
| 58 | [nil]*level, | ||
| 59 | key, | ||
| 60 | value, | ||
| 61 | __pos | ||
| 62 | ] | ||
| 63 | end | ||
| 64 | |||
| 65 | def new_head | ||
| 66 | unless @volume.available?(0) | ||
| 67 | read_node(0) | ||
| 68 | else | ||
| 69 | _head = new_node(@maxlevel, "\x00" * key_length, "\x00" * value_length) | ||
| 70 | save_node!(_head) | ||
| 71 | end | ||
| 72 | end | ||
| 73 | |||
| 74 | def save_node!(node) | ||
| 75 | node_levels = node[0].map{|v| v.nil? ? -1 : v[-1]} | ||
| 76 | packed = ([maxlevel]+node_levels).pack("CN#{node_levels.size}") | ||
| 77 | key = node[-3] | ||
| 78 | value = node[-2] | ||
| 79 | |||
| 80 | if (szd = maxlevel - node_levels.size) > 0 | ||
| 81 | packed += "\xff\xff\xff\xff"*szd | ||
| 82 | end | ||
| 83 | |||
| 84 | if node[-1] == -1 # unsaved | ||
| 85 | node[-1] = @volume.insert!(packed + key + value) | ||
| 86 | else | ||
| 87 | @volume.write!(node[-1],packed + key + value) | ||
| 88 | end | ||
| 89 | @head = node if node[-1] == 0 | ||
| 90 | node | ||
| 91 | end | ||
| 92 | |||
| 93 | def read_node(position) | ||
| 94 | _node = @volume.read(position) | ||
| 95 | level = _node[0,1].unpack('C')[0] | ||
| 96 | links = _node[1,maxlevel*4].unpack("N#{level}") | ||
| 97 | node = [ | ||
| 98 | LazyMappingArray.new(links).map_with do |v| | ||
| 99 | v == 4294967295 ? nil : read_node(v) | ||
| 100 | end.unmap_with {|v| v[-1] }, | ||
| 101 | _node[maxlevel*4 + 1,key_length], | ||
| 102 | _node[maxlevel*4 + 1 + key_length, value_length], | ||
| 103 | position | ||
| 104 | ] | ||
| 105 | end | ||
| 106 | |||
| 107 | |||
| 108 | end | ||
| 109 | end |
|   | |||
| 1 | module StrokeDB | ||
| 2 | class FixedLengthSkiplistVolume < SimpleSkiplist | ||
| 3 | |||
| 4 | def initialize(options = {}) | ||
| 5 | @options = options.stringify_keys | ||
| 6 | @volume = MapVolume.new(:record_size => (@options['maxlevel']||DEFAULT_MAXLEVEL) * 4 + 1 + | ||
| 7 | @options['key_length'] + @options['value_length'], :path => @options['path']) | ||
| 8 | @nodes = {} | ||
| 9 | super(nil,:maxlevel => @options['maxlevel'], :probability => @options['probability']) | ||
| 10 | end | ||
| 11 | |||
| 12 | def key_length | ||
| 13 | @options['key_length'] | ||
| 14 | end | ||
| 15 | |||
| 16 | def value_length | ||
| 17 | @options['value_length'] | ||
| 18 | end | ||
| 19 | |||
| 20 | def path | ||
| 21 | @options['path'] | ||
| 22 | end | ||
| 23 | |||
| 24 | def close! | ||
| 25 | @volume.close! | ||
| 26 | end | ||
| 27 | |||
| 28 | def inspect | ||
| 29 | "#<StrokeDB::FixedLengthSkiplistVolume:0x#{object_id.to_s(16)} path: #{path} key_length: #{key_length} value_length: #{value_length}" | ||
| 30 | end | ||
| 31 | |||
| 32 | private | ||
| 33 | |||
| 34 | # SimpleSkiplist overrides | ||
| 35 | |||
| 36 | |||
| 37 | def node_next(x, level) | ||
| 38 | if node = x[0][level] | ||
| 39 | read_node(node[-1]) | ||
| 40 | else | ||
| 41 | nil | ||
| 42 | end | ||
| 43 | end | ||
| 44 | |||
| 45 | def node_set_value!(x, value) | ||
| 46 | x[-2] = value | ||
| 47 | save_node!(x) | ||
| 48 | end | ||
| 49 | |||
| 50 | def node_insert_after!(x, prev, level) | ||
| 51 | x[0][level] = prev[0][level] | ||
| 52 | prev[0][level] = save_node!(x) | ||
| 53 | save_node!(prev) | ||
| 54 | end | ||
| 55 | |||
| 56 | def new_node(level, key, value, __pos = -1) | ||
| 57 | [ | ||
| 58 | [nil]*level, | ||
| 59 | key, | ||
| 60 | value, | ||
| 61 | __pos | ||
| 62 | ] | ||
| 63 | end | ||
| 64 | |||
| 65 | def new_head | ||
| 66 | unless @volume.available?(0) | ||
| 67 | read_node(0) | ||
| 68 | else | ||
| 69 | _head = new_node(@maxlevel, "\x00" * key_length, "\x00" * value_length) | ||
| 70 | save_node!(_head) | ||
| 71 | end | ||
| 72 | end | ||
| 73 | |||
| 74 | def save_node!(node) | ||
| 75 | node_levels = node[0].map{|v| v.nil? ? -1 : v[-1]} | ||
| 76 | packed = ([maxlevel]+node_levels).pack("CN#{node_levels.size}") | ||
| 77 | key = node[-3] | ||
| 78 | value = node[-2] | ||
| 79 | |||
| 80 | if (szd = maxlevel - node_levels.size) > 0 | ||
| 81 | packed += "\xff\xff\xff\xff"*szd | ||
| 82 | end | ||
| 83 | |||
| 84 | if node[-1] == -1 # unsaved | ||
| 85 | node[-1] = @volume.insert!(packed + key + value) | ||
| 86 | else | ||
| 87 | @volume.write!(node[-1],packed + key + value) | ||
| 88 | end | ||
| 89 | @head = node if node[-1] == 0 | ||
| 90 | node | ||
| 91 | end | ||
| 92 | |||
| 93 | def read_node(position) | ||
| 94 | _node = @volume.read(position) | ||
| 95 | level = _node[0,1].unpack('C')[0] | ||
| 96 | links = _node[1,maxlevel*4].unpack("N#{level}") | ||
| 97 | node = [ | ||
| 98 | LazyMappingArray.new(links).map_with do |v| | ||
| 99 | v == 4294967295 ? nil : read_node(v) | ||
| 100 | end.unmap_with {|v| v[-1] }, | ||
| 101 | _node[maxlevel*4 + 1,key_length], | ||
| 102 | _node[maxlevel*4 + 1 + key_length, value_length], | ||
| 103 | position | ||
| 104 | ] | ||
| 105 | end | ||
| 106 | |||
| 107 | |||
| 108 | end | ||
| 109 | end |

