func (v *Varchar) UnsafeGet(a uint64) (bytes []byte, err error) { rbytes, err := v.unsafeGet(a) if err != nil { return nil, err } m := asRunMeta(rbytes) fullLength := v.allocAmt(int(m.length)) blks := uint64(v.blksNeeded(fullLength)) offset, start, _ := v.startOffsetBlks(a) for offset+uint64(fullLength) >= blks*uint64(v.bf.BlockSize()) { blks++ } size, err := v.bf.Size() if err != nil { return nil, err } for start+blks*uint64(v.bf.BlockSize()) > uint64(size) { blks-- } allBytes, err := v.bf.Get(start, blks) if err != nil { return nil, err } err = v.bf.Release(allBytes) if err != nil { return nil, err } bytes = allBytes[offset:] flags := consts.AsFlag(bytes) if flags&consts.VARCHAR_RUN == 0 { return nil, errors.Errorf("bad address, was not a run block") } r := asRun(bytes) return r.bytes[:r.meta.length], nil }
// Interact with the contents of the varchar. The bytes passed into the // callback are UNSAFE. You could cause a segmentation fault if you // simply copy the *slice* out of the function. You need to copy the // data instead. // // The right way: // // var myBytes []byte // err = v.Do(a, func(bytes []byte) error { // myBytes = make([]byte, len(bytes)) // copy(myBytes, bytes) // return nil // }) // if err != nil { // log.Fatal(err) // } // // you can of course interact with the bytes in the callback in any way // you want as long as no pointers escape. You can even change the // values of the bytes (and these changes will be persisted). However, // you cannot change the length of the varchar. func (v *Varchar) Do(a uint64, do func([]byte) error) (err error) { return v.doRun(a, func(m *varRunMeta) error { fullLength := v.allocAmt(int(m.length)) blks := uint64(v.blksNeeded(fullLength)) offset, start, _ := v.startOffsetBlks(a) for offset+uint64(fullLength) >= blks*uint64(v.bf.BlockSize()) { blks++ } size, err := v.bf.Size() if err != nil { return err } for start+blks*uint64(v.bf.BlockSize()) > uint64(size) { blks-- } return v.bf.Do(start, blks, func(bytes []byte) error { bytes = bytes[offset:] flags := consts.AsFlag(bytes) if flags&consts.VARCHAR_RUN == 0 { return errors.Errorf("bad address, was not a run block") } r := asRun(bytes) return do(r.bytes[:r.meta.length]) }) }) }
func (self *BpTree) do( a uint64, internalDo func(*internal) error, leafDo func(*leaf) error, ) error { return self.bf.Do(a, 1, func(bytes []byte) error { flags := consts.AsFlag(bytes) if flags&consts.INTERNAL != 0 { return internalDo(asInternal(bytes)) } else if flags&consts.LEAF != 0 { return leafDo(asLeaf(bytes)) } else { return errors.Errorf("Unknown block type") } }) }
func (l *List) do( a uint64, doCtrl func(*ctrlBlk) error, doIdx func(*idxBlk) error, ) error { return l.bf.Do(a, 1, func(bytes []byte) error { flags := consts.AsFlag(bytes) if flags == consts.LIST_CTRL { return doCtrl(l.asCtrl(bytes)) } else if flags == consts.LIST_IDX { return doIdx(l.asIdx(bytes)) } else { return errors.Errorf("Unknown block type, %v at %v", flags, a) } }) }
/* right is only set on split left is always set. * - When split is false left is the pointer to block * - When split is true left is the pointer to the new left block */ func (self *BpTree) insert(n uint64, key, value []byte, allowDups bool) (a, b uint64, err error) { var flags consts.Flag err = self.bf.Do(n, 1, func(bytes []byte) error { flags = consts.AsFlag(bytes) return nil }) if err != nil { return 0, 0, err } if flags&consts.INTERNAL != 0 { return self.internalInsert(n, key, value, allowDups) } else if flags&consts.LEAF != 0 { return self.leafInsert(n, key, value, allowDups) } else { return 0, 0, errors.Errorf("Unknown block type") } }
func (self *BpTree) verify(parent uint64, idx int, n, sibling uint64) (err error) { var flags consts.Flag err = self.bf.Do(n, 1, func(bytes []byte) error { flags = consts.AsFlag(bytes) return nil }) if err != nil { return err } if flags&consts.INTERNAL != 0 { return self.internalVerify(parent, idx, n, sibling) } else if flags&consts.LEAF != 0 { return self.leafVerify(parent, idx, n, sibling) } else { return errors.Errorf("Unknown block type") } }
func (self *BpTree) delete(parent, n, sibling uint64, key []byte, where func([]byte) bool) (a uint64, err error) { var flags consts.Flag err = self.bf.Do(n, 1, func(bytes []byte) error { flags = consts.AsFlag(bytes) return nil }) if err != nil { return 0, err } if flags&consts.INTERNAL != 0 { return self.internalDelete(parent, n, sibling, key, where) } else if flags&consts.LEAF != 0 { return self.leafDelete(parent, n, sibling, key, where) } else { return 0, errors.Errorf("Unknown block type") } }
func (self *BpTree) lastKey(n uint64) (a uint64, i int, err error) { var flags consts.Flag err = self.bf.Do(n, 1, func(bytes []byte) error { flags = consts.AsFlag(bytes) return nil }) if err != nil { return 0, 0, err } if flags&consts.INTERNAL != 0 { return self.internalLastKey(n) } else if flags&consts.LEAF != 0 { return self.leafLastKey(n) } else { return 0, 0, errors.Errorf("Unknown block type") } }
func (self *BpTree) _getStart(n uint64, key []byte) (a uint64, i int, err error) { var flags consts.Flag err = self.bf.Do(n, 1, func(bytes []byte) error { flags = consts.AsFlag(bytes) return nil }) if err != nil { return 0, 0, err } if flags&consts.INTERNAL != 0 { return self.internalGetStart(n, key) } else if flags&consts.LEAF != 0 { return self.leafGetStart(n, key, false, 0) } else { return 0, 0, errors.Errorf("Unknown block type") } }
func (v *Varchar) do( a uint64, ctrlDo func(*varCtrl) error, freeDo func(*varFree) error, runDo func(*varRunMeta) error, ) error { offset, start, blks := v.startOffsetBlks(a) return v.bf.Do(start, blks, func(bytes []byte) error { bytes = bytes[offset:] flags := consts.AsFlag(bytes) if flags == consts.VARCHAR_CTRL { return ctrlDo(asCtrl(bytes)) } else if flags == consts.VARCHAR_FREE { return freeDo(asFree(bytes)) } else if flags == consts.VARCHAR_RUN { return runDo(asRunMeta(bytes)) } else { return errors.Errorf("Unknown block type, %v", flags) } }) }