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

- old
+ new

@@ -76,11 +76,11 @@ @children = children || [] @values = nil end end - # Create a new SpaceTreeNode. This method should be used for the creation + # Create a new BTreeNode. This method should be used for the creation # of new nodes instead of calling the constructor directly. # @param tree [BTree] The tree the new node should belong to # @param parent [BTreeNode] The parent node # @param is_leaf [Boolean] True if the node has no children, false # otherwise @@ -128,11 +128,12 @@ PEROBS.log.fatal "Checksum failure in BTreeNode entry @#{address}" end ary = bytes.unpack(BTreeNode::node_bytes_format(tree)) # Read is_leaf if ary[0] != 0 && ary[0] != 1 - PEROBS.log.fatal "First byte of a BTreeNode entry must be 0 or 1" + PEROBS.log.fatal "First byte of a BTreeNode entry at address " + + "#{address} must be 0 or 1 but is #{ary[0]}" end is_leaf = ary[0] == 0 ? false : true # This is the number of keys this node has. key_count = ary[1] data_count = ary[2] @@ -348,10 +349,11 @@ # @return [BTreeNodeLink] common parent of the two nodes def split_node unless @parent # The node is the root node. We need to create a parent node first. self.parent = link(BTreeNode::create(@tree, nil, false)) + @tree.node_cache.insert(self) @parent.set_child(0, self) @tree.set_root(@parent) end # Create the new sibling that will take the 2nd half of the @@ -380,30 +382,29 @@ if @keys.size >= @tree.order PEROBS.log.fatal "Cannot insert into a full BTreeNode" end i = search_key_index(key) + @tree.node_cache.insert(self) if @keys[i] == key # Overwrite existing entries @keys[i] = key if is_leaf @values[i] = value_or_child else @children[i + 1] = link(value_or_child) end - @tree.node_cache.insert(self) return false else # Create a new entry @keys.insert(i, key) if is_leaf @values.insert(i, value_or_child) else @children.insert(i + 1, link(value_or_child)) end - @tree.node_cache.insert(self) return true end end @@ -415,12 +416,12 @@ "@#{@node_address}" end update_branch_key(key) if index == 0 # Delete the corresponding value. - removed_value = @values.delete_at(index) @tree.node_cache.insert(self) + removed_value = @values.delete_at(index) if @keys.length < min_keys if @prev_sibling && @prev_sibling.parent == @parent borrow_from_previous_sibling(@prev_sibling) || @prev_sibling.merge_with_leaf_node(self) @@ -479,28 +480,28 @@ def merge_with_leaf_node(node) if @keys.length + node.keys.length > @tree.order PEROBS.log.fatal "Leaf nodes are too big to merge" end + @tree.node_cache.insert(self) @keys += node.keys @values += node.values - @tree.node_cache.insert(self) node.parent.remove_child(node) end def merge_with_branch_node(node) if @keys.length + 1 + node.keys.length > @tree.order PEROBS.log.fatal "Branch nodes are too big to merge" end index = @parent.search_node_index(node) - 1 + @tree.node_cache.insert(self) @keys << @parent.keys[index] @keys += node.keys node.children.each { |c| c.parent = link(self) } @children += node.children - @tree.node_cache.insert(self) node.parent.remove_child(node) end def search_node_index(node) @@ -523,10 +524,11 @@ if dest_node.is_leaf != @is_leaf PEROBS.log.fatal "Source #{@is_leaf} and destination " + "#{dest_node.is_leaf} node must be of same kind" end + @tree.node_cache.insert(dest_node) dest_node.keys[dst_idx, count] = @keys[src_idx, count] if @is_leaf # For leaves we copy the keys and corresponding values. dest_node.values[dst_idx, count] = @values[src_idx, count] else @@ -535,64 +537,62 @@ # moved-up key. (count + 1).times do |i| dest_node.set_child(dst_idx + i, @children[src_idx + i]) end end - @tree.node_cache.insert(dest_node) end def parent=(p) - @parent = p @tree.node_cache.insert(self) + @parent = p p end def prev_sibling=(node) + @tree.node_cache.insert(self) @prev_sibling = node if node.nil? && @is_leaf # If this node is a leaf node without a previous sibling we need to # register it as the first leaf node. @tree.set_first_leaf(BTreeNodeLink.new(@tree, self)) end - @tree.node_cache.insert(self) - node end def next_sibling=(node) - @next_sibling = node @tree.node_cache.insert(self) + @next_sibling = node if node.nil? && @is_leaf # If this node is a leaf node without a next sibling we need to # register it as the last leaf node. @tree.set_last_leaf(BTreeNodeLink.new(@tree, self)) end node end def set_child(index, child) + @tree.node_cache.insert(self) if child @children[index] = link(child) @children[index].parent = link(self) else @children[index] = nil end - @tree.node_cache.insert(self) child end def trim(idx) + @tree.node_cache.insert(self) @keys.slice!(idx, @keys.length - idx) if @is_leaf @values.slice!(idx, @values.length - idx) else @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 # either the index of an exact match or the index of the position where # the given key would have to be inserted.