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