github.com/coocood/badger@v1.5.1-0.20200528065104-c02ac3616d04/util.go (about) 1 /* 2 * Copyright 2017 Dgraph Labs, Inc. and Contributors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package badger 18 19 import ( 20 "io/ioutil" 21 "math/rand" 22 "sync/atomic" 23 "time" 24 25 "github.com/coocood/badger/table/sstable" 26 "github.com/coocood/badger/y" 27 "github.com/pingcap/errors" 28 ) 29 30 // summary is produced when DB is closed. Currently it is used only for testing. 31 type summary struct { 32 fileIDs map[uint64]bool 33 } 34 35 func (s *levelsController) getSummary() *summary { 36 out := &summary{ 37 fileIDs: make(map[uint64]bool), 38 } 39 for _, l := range s.levels { 40 l.getSummary(out) 41 } 42 return out 43 } 44 45 func (s *levelHandler) getSummary(sum *summary) { 46 s.RLock() 47 defer s.RUnlock() 48 for _, t := range s.tables { 49 sum.fileIDs[t.ID()] = true 50 } 51 } 52 53 func (s *DB) validate() error { return s.lc.validate() } 54 55 func (s *levelsController) validate() error { 56 for _, l := range s.levels { 57 if err := l.validate(); err != nil { 58 return errors.Wrap(err, "Levels Controller") 59 } 60 } 61 return nil 62 } 63 64 // Check does some sanity check on one level of data or in-memory index. 65 func (s *levelHandler) validate() error { 66 if s.level == 0 { 67 return nil 68 } 69 70 s.RLock() 71 defer s.RUnlock() 72 numTables := len(s.tables) 73 for j := 1; j < numTables; j++ { 74 if j >= len(s.tables) { 75 return errors.Errorf("Level %d, j=%d numTables=%d", s.level, j, numTables) 76 } 77 78 if s.tables[j-1].Biggest().Compare(s.tables[j].Smallest()) >= 0 { 79 return errors.Errorf( 80 "Inter: %q vs %q: level=%d j=%d numTables=%d", 81 string(s.tables[j-1].Biggest().UserKey), string(s.tables[j].Smallest().UserKey), s.level, j, numTables) 82 } 83 84 if s.tables[j].Smallest().Compare(s.tables[j].Biggest()) > 0 { 85 return errors.Errorf( 86 "Intra: %q vs %q: level=%d j=%d numTables=%d", 87 s.tables[j].Smallest(), s.tables[j].Biggest(), s.level, j, numTables) 88 } 89 } 90 return nil 91 } 92 93 // func (s *KV) debugPrintMore() { s.lc.debugPrintMore() } 94 95 // // debugPrintMore shows key ranges of each level. 96 // func (s *levelsController) debugPrintMore() { 97 // s.Lock() 98 // defer s.Unlock() 99 // for i := 0; i < s.kv.opt.MaxLevels; i++ { 100 // s.levels[i].debugPrintMore() 101 // } 102 // } 103 104 // func (s *levelHandler) debugPrintMore() { 105 // s.RLock() 106 // defer s.RUnlock() 107 // s.elog.Printf("Level %d:", s.level) 108 // for _, t := range s.tables { 109 // y.Printf(" [%s, %s]", t.Smallest(), t.Biggest()) 110 // } 111 // y.Printf("\n") 112 // } 113 114 // reserveFileID reserves a unique file id. 115 func (s *levelsController) reserveFileID() uint64 { 116 id := atomic.AddUint64(&s.nextFileID, 1) 117 return id - 1 118 } 119 120 func getIDMap(dir string) map[uint64]struct{} { 121 fileInfos, err := ioutil.ReadDir(dir) 122 y.Check(err) 123 idMap := make(map[uint64]struct{}) 124 for _, info := range fileInfos { 125 if info.IsDir() { 126 continue 127 } 128 fileID, ok := sstable.ParseFileID(info.Name()) 129 if !ok { 130 continue 131 } 132 idMap[fileID] = struct{}{} 133 } 134 return idMap 135 } 136 137 func init() { 138 rand.Seed(time.Now().UnixNano()) 139 }