2021-12-04 16:42:11 +00:00

81 lines
2.1 KiB
Go

package graviton
import "fmt"
import "math"
import "crypto/rand"
func (t *Tree) GetName() (string) {
return t.treename
}
// Random returns a random key,value from the tree, provided a tree has keys
// the following are limitations
// a tree containing 0 key, value pairs will return err
// randomness depends on number of keys, if tree contains only 1 value, it will be ported etc
func (t *Tree) Random() (k, v []byte, err error) {
return t.random(t.root)
}
func (t *Tree) random(cnode node) (k, v []byte, err error) {
switch node := cnode.(type) {
case *inner:
if node.loaded_partial { // if node is loaded partially, load it fully now
if err = node.loadinnerfromstore(t.store); err != nil {
return
}
}
left, right := node.left, node.right
if left != nil && right != nil { // we have an option to choose from left or right randomly
var rbyte [1]byte
if _, err = rand.Read(rbyte[:]); err != nil {
return
}
if rbyte[0]&1 == 1 {
return t.random(right) // descend further
}
return t.random(left) // descend further
}
if right != nil {
return t.random(right) // descend further without any option
}
if left != nil {
return t.random(left) // descend further without any option
}
// we can only reach here if a tree has both left,right nil, ie an empty tree
err = ErrNoMoreKeys
return
case *leaf:
if node.loaded_partial { // if leaf is loaded partially, load it fully now
if err = node.loadfullleaffromstore(t.store); err != nil {
return
}
}
return node.key, node.value, nil
default:
return k, v, fmt.Errorf("unknown node type, corruption")
}
}
// estimate number of keys that exist in the tree
// very crude but only used for use display
func (t *Tree) KeyCountEstimate() (count int64) {
c := t.Cursor()
var depth_array []int
var floatsum float64
for _, _, err := c.First(); err == nil; _, _, err = c.Next() {
floatsum += float64(len(c.node_path))
depth_array = append(depth_array, len(c.node_path))
if len(depth_array) >= 20 {
break
}
}
if len(depth_array) <= 4 {
return int64(count)
}
avg := floatsum / float64(len(depth_array)+1)
return int64(math.Exp2(avg))
}