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  }