lib/perobs/BTree.rb in perobs-4.1.0 vs lib/perobs/BTree.rb in perobs-4.2.0

- old
+ new

@@ -51,12 +51,12 @@ def initialize(dir, name, order, progressmeter) @dir = dir @name = name @progressmeter = progressmeter - unless order > 2 - PEROBS.log.fatal "BTree order must be larger than 2, not #{order}" + unless order > 4 + PEROBS.log.fatal "BTree order must be larger than 4, not #{order}" end unless order % 2 == 1 PEROBS.log.fatal "BTree order must be an uneven number, not #{order}" end unless order < 2 ** 16 - 1 @@ -68,11 +68,11 @@ @nodes = EquiBlobsFile.new(@dir, @name, @progressmeter, BTreeNode::node_bytes(@order)) @nodes.register_custom_data('first_leaf') @nodes.register_custom_data('last_leaf') @nodes.register_custom_data('btree_size') - @node_cache = PersistentObjectCache.new(16384, 5000, BTreeNode, self) + @node_cache = PersistentObjectCache.new(2**16, -1, BTreeNode, self) @root = @first_leaf = @last_leaf = nil @size = 0 # This BTree implementation uses a write cache to improve write # performance of multiple successive read/write operations. This also @@ -115,16 +115,14 @@ @size = @nodes.get_custom_data('btree_size') end # Close the tree file. def close - - def val_perc(value, total) - "#{value} (#{(value.to_f / total*100.0).to_i}%)" - end - sync + PEROBS.log.info "BTree file #{@name} has currently " + + "#{@nodes.total_entries} used entries and #{@nodes.total_spaces} " + + "unused entries" @nodes.close @root = nil end # @return true if file is currently open @@ -163,25 +161,38 @@ def check(&block) sync return false unless @nodes.check entries = 0 - res = true + stats = nil @progressmeter.start('Checking index structure', @size) do |pm| - res = @root.check do |k, v| + stats = @root.check do |k, v| pm.update(entries += 1) block_given? ? yield(k, v) : true end end + return false unless stats + unless entries == @size PEROBS.log.error "The BTree size (#{@size}) and the number of " + "found entries (#{entries}) don't match" return false end + unless stats.nodes_count == @nodes.total_entries + PEROBS.log.error "The BTree nodes count (#{stats.nodes_count}) and " + + "the number of entries in the nodes file (#{@nodes.total_entries}) " + + "don't match" + return false + end + PEROBS.log.info "Statistics for the BTree #{@name}: " + + "Number of nodes: #{stats.nodes_count}; " + + "Branch depth: #{stats.branch_depth}; " + + "Number of leave nodes: #{stats.leave_nodes}; " + + "Number of leaves: #{stats.leaves}" - res + !stats.nil? end # Register a new node as root node of the tree. # @param node [BTreeNode] def set_root(node) @@ -206,19 +217,28 @@ # Insert a new value into the tree using the key as a unique index. If the # key already exists the old value will be overwritten. # @param key [Integer] Unique key # @param value [Integer] value def insert(key, value) - @size += 1 if @root.insert(key, value) - @node_cache.flush + if @root.insert(key, value) + @size += 1 + @node_cache.flush + end end # Retrieve the value associated with the given key. If no entry was found, # return nil. # @param key [Integer] Unique key # @return [Integer or nil] found value or nil def get(key) @root.get(key) + end + + # Either return the key/value pair that exactly matches the key or a + # key/value pair that has a key that is at least min_miss_increment larger + # than the key. + def get_best_match(key, min_miss_increment) + @root.get_best_match(key, min_miss_increment) end # Find and remove the value associated with the given key. If no entry was # found, return nil, otherwise the found value. def remove(key)