/* a pure leaf split has two cases: * 1) the inserted key is less than the current pure block. * - a new block should be created before the current block * - the key should be put in it * 2) the inserted key is greater than or equal to the pure block. * - the end of run of pure blocks should be found * - if the key is equal to pure block and the last block is not full insert * the new kv * - else split by making a new block after the last block in the run * and putting the new key there. * - always return the current block as "a" and the new block as "b" */ func (self *BpNode) pure_leaf_split(key types.Sortable, value interface{}) (a, b *BpNode, err error) { if self.Internal() || !self.Pure() { return nil, nil, errors.BpTreeError("Expected a pure leaf node") } if key.Less(self.keys[0]) { a = NewLeaf(self.NodeSize(), self.no_dup) b = self if err := a.put_kv(key, value); err != nil { return nil, nil, err } insert_linked_list_node(a, b.prev, b) return a, b, nil } else { a = self e := self.find_end_of_pure_run() if e.keys[0].Equals(key) && !e.Full() { if err := e.put_kv(key, value); err != nil { return nil, nil, err } return a, nil, nil } else { b = NewLeaf(self.NodeSize(), self.no_dup) if err := b.put_kv(key, value); err != nil { return nil, nil, err } insert_linked_list_node(b, e, e.next) if e.keys[0].Equals(key) { return a, nil, nil } return a, b, nil } } }
func (self *BpNode) forward(from, to types.Sortable) (li loc_iterator) { j, l := self.get_start(from) end := false j-- li = func() (i int, leaf *BpNode, next loc_iterator) { j, l, end = next_location(j, l) if end || to.Less(l.keys[j]) { return -1, nil, nil } return j, l, li } return li }
/* On split * - first assert that the key to be inserted is not already in the block. * - Make a new block * - balance the two blocks. * - insert the new key/pointer combo into the correct block */ func (self *BpNode) internal_split(key types.Sortable, ptr *BpNode) (a, b *BpNode, err error) { if !self.Internal() { return nil, nil, errors.BpTreeError("Expected a internal node") } if self.has(key) { return nil, nil, errors.BpTreeError("Tried to split an internal block on duplicate key") } a = self b = NewInternal(self.NodeSize()) balance_nodes(a, b) if key.Less(b.keys[0]) { if err := a.put_kp(key, ptr); err != nil { return nil, nil, err } } else { if err := b.put_kp(key, ptr); err != nil { return nil, nil, err } } return a, b, nil }
/* on leaf split if the block is pure then it will defer to pure_leaf_split * else * - a new block will be made and inserted after this one * - the two blocks will be balanced with balanced_nodes * - if the key is less than b.keys[0] it will go in a else b */ func (self *BpNode) leaf_split(key types.Sortable, value interface{}) (a, b *BpNode, err error) { if self.Internal() { return nil, nil, errors.BpTreeError("Expected a leaf node") } if self.Pure() { return self.pure_leaf_split(key, value) } a = self b = NewLeaf(self.NodeSize(), self.no_dup) insert_linked_list_node(b, a, a.next) balance_nodes(a, b) if key.Less(b.keys[0]) { if err := a.put_kv(key, value); err != nil { return nil, nil, err } } else { if err := b.put_kv(key, value); err != nil { return nil, nil, err } } return a, b, nil }
func (self *BpNode) find(key types.Sortable) (int, bool) { var l int = 0 var r int = len(self.keys) - 1 var m int for l <= r { m = ((r - l) >> 1) + l if key.Less(self.keys[m]) { r = m - 1 } else if key.Equals(self.keys[m]) { for j := m; j >= 0; j-- { if j == 0 || !key.Equals(self.keys[j-1]) { return j, true } } } else { l = m + 1 } } return l, false }