github.com/scottcagno/storage@v1.8.0/pkg/_junk/_lsmtree/sstable/sparse.go (about) 1 package sstable 2 3 import ( 4 "fmt" 5 "github.com/scottcagno/storage/pkg/_junk/_lsmtree/container/rbtree" 6 "log" 7 "math" 8 "path/filepath" 9 ) 10 11 type SparseIndex struct { 12 base string 13 index int64 14 rbt *rbtree.RBTree 15 } 16 17 func (spi *SparseIndex) String() string { 18 ss := fmt.Sprintf("sparseIndex.base=%q, sparseIndex.index=%d, sparseIndex.rbt=[\n", spi.base, spi.index) 19 spi.rbt.Scan(func(k string, v []byte) bool { 20 ss += fmt.Sprintf("\t%q:%d\n", k, rbtree.ValToInt(v)) 21 return true 22 }) 23 ss += "]\n" 24 return ss 25 } 26 27 func log2(n int64) int64 { 28 if n < 1 { 29 return 0 30 } 31 if n == 1 { 32 n++ 33 } 34 return int64(math.Log2(float64(n))) 35 } 36 37 func OpenSparseIndex(base string, index int64) (*SparseIndex, error) { 38 spi := &SparseIndex{ 39 base: base, 40 index: index, 41 rbt: rbtree.NewRBTree(), 42 } 43 ssi, err := OpenSSIndex(base, index) 44 if err != nil { 45 return nil, err 46 } 47 count := int64(ssi.Len()) 48 n, i := log2(count), int64(0) 49 ssi.Scan(func(k string, off int64) bool { 50 if i%(count/n) == 0 { 51 log.Printf("adding to sparse index: k=%q, v=%d\n", k, off) 52 spi.rbt.Put(k, rbtree.IntToVal(off)) 53 } 54 i++ 55 return true 56 }) 57 return spi, nil 58 } 59 60 func (spi *SparseIndex) GetClose(k string) (string, int64) { 61 v, _ := spi.rbt.GetNearMin(k) 62 path := filepath.Join(spi.base, DataFileNameFromIndex(spi.index)) 63 offset := rbtree.ValToInt(v) 64 return path, offset 65 } 66 67 func (spi *SparseIndex) First() string { 68 k, _, _ := spi.rbt.Min() 69 return k 70 } 71 72 func (spi *SparseIndex) Last() string { 73 k, _, _ := spi.rbt.Max() 74 return k 75 } 76 77 func (spi *SparseIndex) HasKey(k string) bool { 78 _, prev, next, ok := spi.rbt.GetApproxKeyPrevNext(k) 79 if ok { 80 return true 81 } 82 if prev < k && k < next { 83 return true 84 } 85 return false 86 }