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)