lib/perobs/BTreeNode.rb in perobs-4.2.0 vs lib/perobs/BTreeNode.rb in perobs-4.3.0

- old
+ new

@@ -57,26 +57,26 @@ # backing store # @param is_leaf [Boolean] true if the node should be a leaf node, false # if not def initialize(tree, node_address = nil, parent = nil, is_leaf = true, prev_sibling = nil, next_sibling = nil, - keys = [], values = [], children = []) + keys = nil, values = nil, children = nil) @tree = tree if node_address == 0 PEROBS.log.fatal "Node address may not be 0" end @node_address = node_address @parent = link(parent) @prev_sibling = link(prev_sibling) @next_sibling = link(next_sibling) - @keys = keys + @keys = keys || [] if (@is_leaf = is_leaf) - @values = values - @children = [] + @values = values || [] + @children = nil else - @children = children - @values = [] + @children = children || [] + @values = nil end end # Create a new SpaceTreeNode. This method should be used for the creation # of new nodes instead of calling the constructor directly. @@ -583,15 +583,15 @@ child end def trim(idx) - @keys = @keys[0..idx - 1] + @keys.slice!(idx, @keys.length - idx) if @is_leaf - @values = @values[0..idx - 1] + @values.slice!(idx, @values.length - idx) else - @children = @children[0..idx] + @children.slice!(idx + 1, @children.length - idx - 1) end @tree.node_cache.insert(self) end # Search the keys of the node that fits the given key. The result is @@ -652,17 +652,22 @@ # Check consistency of the node and all subsequent nodes. In case an error # is found, a message is logged and false is returned. # @yield [key, value] # @return [nil or Hash] nil in case of errors or a hash with some # statistical information about the tree - def check + def check(&block) stats = Stats.new(nil, 0, 0, 0) traverse do |node, position, stack| if position == 0 stats.nodes_count += 1 if node.parent + unless node.parent.is_a?(BTreeNodeLink) + node.error "parent is a #{node.parent.class} instead of a " + + "BTreeNodeLink" + return nil + end # After a split the nodes will only have half the maximum keys. # For branch nodes one of the split nodes will have even 1 key # less as this will become the branch key in a parent node. if node.keys.size < min_keys - (node.is_leaf ? 0 : 1) node.error "BTreeNode #{node.node_address} has too few keys" @@ -693,10 +698,20 @@ return nil end else stats.branch_depth = node.tree_level end + if node.prev_sibling && !node.prev_sibling.is_a?(BTreeNodeLink) + node.error "prev_sibling is a #{node.prev_sibling.class} " + + "instead of a BTreeNodeLink" + return nil + end + if node.next_sibling && !node.next_sibling.is_a?(BTreeNodeLink) + node.error "next_sibling is a #{node.next_sibling.class} " + + "instead of a BTreeNodeLink" + return nil + end if node.prev_sibling.nil? && @tree.first_leaf != node node.error "Leaf node #{node.node_address} has no previous " + "sibling but is not the first leaf of the tree" return nil end @@ -706,28 +721,28 @@ return nil end unless node.keys.size == node.values.size node.error "Key count (#{node.keys.size}) and value " + "count (#{node.values.size}) don't match" - return nil + return nil end - unless node.children.empty? + unless node.children.nil? node.error "@children must be nil for a leaf node" return nil end stats.leave_nodes += 1 stats.leaves += node.keys.length else - unless node.values.empty? + unless node.values.nil? node.error "@values must be nil for a branch node" return nil end unless node.children.size == node.keys.size + 1 node.error "Key count (#{node.keys.size}) must be one " + "less than children count (#{node.children.size})" - return nil + return nil end node.children.each_with_index do |child, i| unless child.is_a?(BTreeNodeLink) node.error "Child #{i} is of class #{child.class} " + "instead of BTreeNodeLink" @@ -787,10 +802,12 @@ return nil end else if block_given? # If a block was given, call this block with the key and value. - return nil unless yield(node.keys[index], node.values[index]) + unless yield(node.keys[index], node.values[index]) + return nil + end end end end end