github.com/zuoyebang/bitalosdb@v1.1.1-0.20240516111551-79a8c4d8ce20/bitpage/skl_table.go (about) 1 // Copyright 2021 The Bitalosdb author(hustxrb@163.com) and other contributors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package bitpage 16 17 import ( 18 "fmt" 19 "os" 20 "runtime/debug" 21 ) 22 23 func sklTableEntrySize(keyBytes, valueBytes int) uint64 { 24 return uint64(sklNodeMaxSize(uint32(keyBytes), uint32(valueBytes))) 25 } 26 27 type sklTable struct { 28 bp *Bitpage 29 tbl *table 30 sl *skl 31 ins *Inserter 32 totalCount float64 33 delCount float64 34 } 35 36 func checkSklTable(obj interface{}) { 37 s := obj.(*sklTable) 38 if s.tbl != nil { 39 fmt.Fprintf(os.Stderr, "sklTable(%s) buffer was not freed\n", s.path()) 40 os.Exit(1) 41 } 42 } 43 44 func newSklTable(path string, exist bool, bp *Bitpage) (*sklTable, error) { 45 tbl, err := openTable(path, defaultTableOptions) 46 if err != nil { 47 return nil, err 48 } 49 50 s := &sklTable{ 51 bp: bp, 52 tbl: tbl, 53 ins: &Inserter{}, 54 } 55 56 if exist { 57 s.sl = openSkl(tbl, s, false) 58 } else { 59 sl, err := newSkl(tbl, s, false) 60 if err != nil { 61 return nil, err 62 } 63 s.sl = sl 64 } 65 66 return s, nil 67 } 68 69 func (s *sklTable) kindStatis(kind internalKeyKind) { 70 s.totalCount++ 71 if kind == internalKeyKindDelete { 72 s.delCount++ 73 } 74 } 75 76 func (s *sklTable) delPercent() float64 { 77 if s.delCount == 0 { 78 return 0 79 } 80 return s.delCount / s.totalCount 81 } 82 83 func (s *sklTable) itemCount() int { 84 return int(s.totalCount) 85 } 86 87 func (s *sklTable) readyForFlush() bool { 88 return true 89 } 90 91 func (s *sklTable) get(key []byte, khash uint32) ([]byte, bool, internalKeyKind, func()) { 92 value, exist, kind := s.sl.Get(key, khash) 93 return value, exist, kind, nil 94 } 95 96 func (s *sklTable) prepare(size uint64) error { 97 return s.tbl.checkTableFull(int(size)) 98 } 99 100 func (s *sklTable) newIter(o *iterOptions) internalIterator { 101 return s.sl.NewIter(o.GetLowerBound(), o.GetUpperBound()) 102 } 103 104 func (s *sklTable) inuseBytes() uint64 { 105 return uint64(s.sl.Size()) 106 } 107 108 func (s *sklTable) dataBytes() uint64 { 109 return uint64(s.sl.Size()) 110 } 111 112 func (s *sklTable) close() error { 113 if s.tbl == nil { 114 return nil 115 } 116 117 if err := s.tbl.close(); err != nil { 118 return err 119 } 120 121 s.tbl = nil 122 s.sl.cache.index = nil 123 return nil 124 } 125 126 func (s *sklTable) path() string { 127 if s.tbl == nil { 128 return "" 129 } 130 return s.tbl.path 131 } 132 133 func (s *sklTable) idxFilePath() string { 134 return "" 135 } 136 137 func (s *sklTable) empty() bool { 138 return s.sl.isEmpty() 139 } 140 141 func (s *sklTable) checkIntegrity() { 142 defer func() { 143 if r := recover(); r != nil { 144 s.bp.opts.Logger.Errorf("sklTable checkIntegrity panic path:%s err:%v stack:%s", s.path(), r, string(debug.Stack())) 145 } 146 }() 147 148 s.bp.opts.Logger.Infof("check data integrity start file:%s", s.path()) 149 150 iter := s.newIter(&iterOptions{}) 151 defer iter.Close() 152 153 var count int 154 for k, v := iter.First(); k != nil; k, v = iter.Next() { 155 _ = k.String() 156 _ = v 157 count++ 158 } 159 160 if !s.sl.isEmpty() && count == 0 { 161 panic("empty data") 162 } 163 164 s.bp.opts.Logger.Infof("check data integrity success file:%s", s.path()) 165 }