Beispiel #1
0
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
}
Beispiel #2
0
// 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])
		})
	})
}
Beispiel #3
0
Datei: do.go Projekt: postfix/fs2
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")
		}
	})
}
Beispiel #4
0
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)
		}
	})
}
Beispiel #5
0
/* 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")
	}
}
Beispiel #6
0
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")
	}
}
Beispiel #7
0
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")
	}
}
Beispiel #8
0
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")
	}
}
Beispiel #9
0
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")
	}
}
Beispiel #10
0
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)
		}
	})
}