util.go raw

   1  /*
   2   * SPDX-FileCopyrightText: © Hypermode Inc. <hello@hypermode.com>
   3   * SPDX-License-Identifier: Apache-2.0
   4   */
   5  
   6  package badger
   7  
   8  import (
   9  	"encoding/hex"
  10  	"fmt"
  11  	"math/rand"
  12  	"os"
  13  	"time"
  14  
  15  	"github.com/dgraph-io/badger/v4/table"
  16  	"github.com/dgraph-io/badger/v4/y"
  17  )
  18  
  19  func (s *levelsController) validate() error {
  20  	for _, l := range s.levels {
  21  		if err := l.validate(); err != nil {
  22  			return y.Wrap(err, "Levels Controller")
  23  		}
  24  	}
  25  	return nil
  26  }
  27  
  28  // Check does some sanity check on one level of data or in-memory index.
  29  func (s *levelHandler) validate() error {
  30  	if s.level == 0 {
  31  		return nil
  32  	}
  33  
  34  	s.RLock()
  35  	defer s.RUnlock()
  36  	numTables := len(s.tables)
  37  	for j := 1; j < numTables; j++ {
  38  		if j >= len(s.tables) {
  39  			return fmt.Errorf("Level %d, j=%d numTables=%d", s.level, j, numTables)
  40  		}
  41  
  42  		if y.CompareKeys(s.tables[j-1].Biggest(), s.tables[j].Smallest()) >= 0 {
  43  			return fmt.Errorf(
  44  				"Inter: Biggest(j-1)[%d] \n%s\n vs Smallest(j)[%d]: \n%s\n: "+
  45  					"level=%d j=%d numTables=%d",
  46  				s.tables[j-1].ID(), hex.Dump(s.tables[j-1].Biggest()), s.tables[j].ID(),
  47  				hex.Dump(s.tables[j].Smallest()), s.level, j, numTables)
  48  		}
  49  
  50  		if y.CompareKeys(s.tables[j].Smallest(), s.tables[j].Biggest()) > 0 {
  51  			return fmt.Errorf(
  52  				"Intra: \n%s\n vs \n%s\n: level=%d j=%d numTables=%d",
  53  				hex.Dump(s.tables[j].Smallest()), hex.Dump(s.tables[j].Biggest()), s.level, j, numTables)
  54  		}
  55  	}
  56  	return nil
  57  }
  58  
  59  // func (s *KV) debugPrintMore() { s.lc.debugPrintMore() }
  60  
  61  // // debugPrintMore shows key ranges of each level.
  62  // func (s *levelsController) debugPrintMore() {
  63  // 	s.Lock()
  64  // 	defer s.Unlock()
  65  // 	for i := 0; i < s.kv.opt.MaxLevels; i++ {
  66  // 		s.levels[i].debugPrintMore()
  67  // 	}
  68  // }
  69  
  70  // func (s *levelHandler) debugPrintMore() {
  71  // 	s.RLock()
  72  // 	defer s.RUnlock()
  73  // 	s.elog.Printf("Level %d:", s.level)
  74  // 	for _, t := range s.tables {
  75  // 		y.Printf(" [%s, %s]", t.Smallest(), t.Biggest())
  76  // 	}
  77  // 	y.Printf("\n")
  78  // }
  79  
  80  // reserveFileID reserves a unique file id.
  81  func (s *levelsController) reserveFileID() uint64 {
  82  	id := s.nextFileID.Add(1)
  83  	return id - 1
  84  }
  85  
  86  func getIDMap(dir string) map[uint64]struct{} {
  87  	fileInfos, err := os.ReadDir(dir)
  88  	y.Check(err)
  89  	idMap := make(map[uint64]struct{})
  90  	for _, info := range fileInfos {
  91  		if info.IsDir() {
  92  			continue
  93  		}
  94  		fileID, ok := table.ParseFileID(info.Name())
  95  		if !ok {
  96  			continue
  97  		}
  98  		idMap[fileID] = struct{}{}
  99  	}
 100  	return idMap
 101  }
 102  
 103  func init() {
 104  	rand.Seed(time.Now().UnixNano())
 105  }
 106