github.com/zuoyebang/bitalosdb@v1.1.1-0.20240516111551-79a8c4d8ce20/bitree/bitree.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 bitree 16 17 import ( 18 "bytes" 19 "encoding/binary" 20 "errors" 21 "fmt" 22 "path" 23 24 "github.com/zuoyebang/bitalosdb/bitable" 25 "github.com/zuoyebang/bitalosdb/bithash" 26 "github.com/zuoyebang/bitalosdb/bitpage" 27 "github.com/zuoyebang/bitalosdb/bitree/bdb" 28 "github.com/zuoyebang/bitalosdb/internal/base" 29 "github.com/zuoyebang/bitalosdb/internal/options" 30 "github.com/zuoyebang/bitalosdb/internal/statemachine" 31 "github.com/zuoyebang/bitalosdb/internal/utils" 32 "github.com/zuoyebang/bitalosdb/internal/vfs" 33 ) 34 35 type FS vfs.FS 36 type File vfs.File 37 38 var ( 39 ErrBdbNotExist = errors.New("bitree bdb not exist") 40 ErrBucketNotExist = errors.New("bitree bucket not exist") 41 ) 42 43 type Bitree struct { 44 opts *options.BitreeOptions 45 closed bool 46 kvSeparateSize int 47 index int 48 bdb *bdb.DB 49 txPool *TxPool 50 bpage *bitpage.Bitpage 51 bhash *bithash.Bithash 52 btable *bitable.Bitable 53 dbState *statemachine.DbStateMachine 54 } 55 56 func NewBitree(path string, opts *options.BitreeOptions) (*Bitree, error) { 57 var err error 58 59 t := &Bitree{ 60 opts: opts, 61 index: opts.Index, 62 kvSeparateSize: opts.KvSeparateSize, 63 dbState: opts.DbState, 64 } 65 66 defer func() { 67 if err != nil { 68 if t.bpage != nil { 69 _ = t.bpage.Close() 70 } 71 if t.bhash != nil { 72 _ = t.bhash.Close() 73 } 74 if t.btable != nil { 75 _ = t.btable.Close() 76 } 77 if t.txPool != nil { 78 _ = t.txPool.Close() 79 } 80 if t.bdb != nil { 81 _ = t.bdb.Close() 82 } 83 } 84 }() 85 86 opts.BitpageOpts.CheckExpireCB = t.KvCheckExpire 87 opts.BitpageOpts.BithashDeleteCB = t.bithashDelete 88 opts.BitpageOpts.BitableDeleteCB = t.bitableDelete 89 opts.BitpageOpts.Index = t.index 90 bitpagePath := base.MakeBitpagepath(path, t.index) 91 t.bpage, err = bitpage.Open(bitpagePath, opts.BitpageOpts) 92 if err != nil { 93 return nil, err 94 } 95 96 opts.BdbOpts.CheckPageSplitted = t.checkPageSplitted 97 opts.BdbOpts.Index = t.index 98 bitreePath := base.MakeBitreeFilepath(path, t.index) 99 if err = t.openBdb(bitreePath, opts.BdbOpts); err != nil { 100 return nil, err 101 } 102 if err = t.openTxPool(); err != nil { 103 return nil, err 104 } 105 106 if opts.UseBithash { 107 opts.BithashOpts.Index = t.index 108 bithashPath := base.MakeBithashpath(path, t.index) 109 t.kvSeparateSize = opts.KvSeparateSize 110 t.bhash, err = bithash.Open(bithashPath, opts.BithashOpts) 111 if err != nil { 112 return nil, err 113 } 114 } 115 116 if opts.UseBitable { 117 opts.BitableOpts.Index = t.index 118 opts.BitableOpts.CheckExpireCB = t.KvCheckExpire 119 bitablePath := base.MakeBitablepath(path, t.index) 120 t.btable, err = bitable.Open(t.bhash, bitablePath, opts.BitableOpts) 121 if err != nil { 122 return nil, err 123 } 124 } 125 126 return t, nil 127 } 128 129 func (t *Bitree) Index() int { 130 return t.index 131 } 132 133 func (t *Bitree) Close() error { 134 if t.closed { 135 return nil 136 } 137 138 t.closed = true 139 140 if t.bpage != nil { 141 _ = t.bpage.Close() 142 t.bpage = nil 143 } 144 145 if t.bhash != nil { 146 _ = t.bhash.Close() 147 t.bhash = nil 148 } 149 150 if t.btable != nil { 151 _ = t.btable.Close() 152 t.btable = nil 153 } 154 155 if t.txPool != nil { 156 _ = t.txPool.Close() 157 t.txPool = nil 158 } 159 160 if t.bdb != nil { 161 _ = t.bdb.Close() 162 t.bdb = nil 163 } 164 165 return nil 166 } 167 168 func (t *Bitree) getInternal(key []byte, khash uint32) ([]byte, bool, func()) { 169 pvalue, pexist, pcloser, pkind := t.bitpageGet(key, khash) 170 if pexist || pkind == base.InternalKeyKindDelete { 171 return pvalue, pexist, pcloser 172 } 173 174 tvalue, tcloser, terr := t.bitableGet(key) 175 if terr == base.ErrNotFound { 176 return nil, false, nil 177 } 178 return tvalue, true, func() { 179 _ = tcloser.Close() 180 } 181 } 182 183 func (t *Bitree) Get(key []byte, khash uint32) ([]byte, bool, func()) { 184 var err error 185 var value []byte 186 var putPool func() = nil 187 188 ivalue, iexist, icloser := t.getInternal(key, khash) 189 if !iexist { 190 return nil, false, nil 191 } 192 193 iv := base.DecodeInternalValue(ivalue) 194 if iv.Kind() == base.InternalKeyKindSetBithash { 195 if !base.CheckValueValidByKeySetBithash(iv.UserValue) { 196 icloser() 197 return nil, false, nil 198 } 199 200 fn := binary.LittleEndian.Uint32(iv.UserValue) 201 value, putPool, err = t.bithashGetByHash(key, khash, fn) 202 if err != nil { 203 icloser() 204 return nil, false, nil 205 } 206 } else { 207 value = iv.UserValue 208 } 209 210 if putPool != nil { 211 return value, true, func() { 212 icloser() 213 putPool() 214 } 215 } else { 216 return value, true, icloser 217 } 218 } 219 220 func (t *Bitree) Exist(key []byte, khash uint32) bool { 221 _, iexist, icloser := t.getInternal(key, khash) 222 if icloser != nil { 223 icloser() 224 } 225 226 return iexist 227 } 228 229 func (t *Bitree) newBitreeIter(o *options.IterOptions) *BitreeIterator { 230 iter := &BitreeIterator{ 231 btree: t, 232 cmp: t.opts.Cmp, 233 ops: o, 234 bdbIter: t.NewBdbIter(), 235 bpageIters: make(map[bitpage.PageNum]*bitpage.PageIterator, 1<<2), 236 } 237 iter.SetBounds(o.GetLowerBound(), o.GetUpperBound()) 238 return iter 239 } 240 241 func (t *Bitree) NewIters(o *options.IterOptions) []base.InternalIterator { 242 iters := make([]base.InternalIterator, 1) 243 iters[0] = t.newBitreeIter(o) 244 245 if t.btable != nil && t.opts.IsFlushedBitableCB() { 246 bitableIter := t.newBitableIter(o) 247 if bitableIter != nil { 248 iters = append(iters, bitableIter) 249 } 250 } 251 252 return iters 253 } 254 255 func (t *Bitree) IsKvSeparate(len int) bool { 256 if !t.opts.UseBithash { 257 return false 258 } 259 260 return len > t.kvSeparateSize 261 } 262 263 func (t *Bitree) Checkpoint(fs vfs.FS, destDir, dbDir string) error { 264 bitpageDest := path.Join(destDir, fs.PathBase(base.MakeBitpagepath(dbDir, t.index))) 265 if err := t.bpage.Checkpoint(fs, bitpageDest); err != nil { 266 return err 267 } 268 269 if t.opts.UseBithash { 270 bithashDest := fs.PathJoin(destDir, fs.PathBase(base.MakeBithashpath(dbDir, t.index))) 271 if err := t.bhash.Checkpoint(fs, bithashDest); err != nil { 272 return err 273 } 274 } 275 276 if t.btable != nil && t.opts.IsFlushedBitableCB() { 277 bitableDest := fs.PathJoin(destDir, fs.PathBase(base.MakeBitablepath(dbDir, t.index))) 278 if err := t.btable.Checkpoint(bitableDest); err != nil { 279 return err 280 } 281 } 282 283 return nil 284 } 285 286 func (t *Bitree) BitreeDebugInfo(dataType string) string { 287 if t.bdb == nil || t.bpage == nil { 288 return "" 289 } 290 291 buf := new(bytes.Buffer) 292 293 bdbIter := t.NewBdbIter() 294 defer bdbIter.Close() 295 296 for bdbKey, bdbValue := bdbIter.First(); bdbKey != nil; bdbKey, bdbValue = bdbIter.Next() { 297 pn := bitpage.PageNum(utils.BytesToUint32(bdbValue)) 298 pageInfo := t.bpage.GetPageDebugInfo(pn) 299 fmt.Fprintf(buf, "%s-bitpage%d-%s: pn:%d ct:%s ut:%s split:%d\n", 300 dataType, t.index, bdbKey.String(), pn, 301 utils.FmtUnixMillTime(pageInfo.Ct), 302 utils.FmtUnixMillTime(pageInfo.Ut), 303 pageInfo.SplitState, 304 ) 305 } 306 307 if t.opts.UseBlockCompress { 308 fmt.Fprintf(buf, "%s-bitpage%d-blockCache: %s\n", dataType, t.index, t.bpage.GetCacheMetrics()) 309 } 310 311 return buf.String() 312 } 313 314 func (t *Bitree) DeleteBithashKey(v []byte) { 315 if v == nil { 316 return 317 } 318 319 dv := base.DecodeInternalValue(v) 320 if dv.Kind() == base.InternalKeyKindSetBithash && base.CheckValueValidByKeySetBithash(dv.UserValue) { 321 fn := binary.LittleEndian.Uint32(dv.UserValue) 322 _ = t.bithashDelete(fn) 323 } 324 } 325 326 func (t *Bitree) KvCheckExpire(key, value []byte) bool { 327 dv := base.DecodeInternalValue(value) 328 if dv.Kind() == base.InternalKeyKindSetBithash { 329 isExpire := false 330 if len(dv.UserValue) == 12 { 331 tm := binary.LittleEndian.Uint64(dv.UserValue[4:12]) 332 if tm > 0 { 333 _, nowTime := t.opts.KvTimestampFunc(nil, 2) 334 if tm <= nowTime { 335 isExpire = true 336 } 337 } 338 } 339 if !isExpire { 340 isExpire = t.opts.KvCheckExpire(key, nil) 341 } 342 if isExpire { 343 fn := binary.LittleEndian.Uint32(dv.UserValue) 344 _ = t.bithashDelete(fn) 345 } 346 return isExpire 347 } 348 349 return t.opts.KvCheckExpire(key, dv.UserValue) 350 } 351 352 func (t *Bitree) GetBitpageCount() int { 353 return t.bpage.GetPageCount() 354 } 355 356 func (t *Bitree) ManualFlushBitpage() { 357 t.MaybeScheduleFlush(true) 358 }