github.com/zuoyebang/bitalosdb@v1.1.1-0.20240516111551-79a8c4d8ce20/db.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 bitalosdb 16 17 import ( 18 "context" 19 "io" 20 "sync" 21 "sync/atomic" 22 "time" 23 24 "github.com/cockroachdb/errors" 25 "github.com/zuoyebang/bitalosdb/internal/base" 26 "github.com/zuoyebang/bitalosdb/internal/bitask" 27 "github.com/zuoyebang/bitalosdb/internal/cache" 28 "github.com/zuoyebang/bitalosdb/internal/compress" 29 "github.com/zuoyebang/bitalosdb/internal/consts" 30 "github.com/zuoyebang/bitalosdb/internal/options" 31 "github.com/zuoyebang/bitalosdb/internal/statemachine" 32 "github.com/zuoyebang/bitalosdb/internal/utils" 33 "github.com/zuoyebang/bitalosdb/internal/vfs" 34 "golang.org/x/sync/errgroup" 35 ) 36 37 var ( 38 ErrNotFound = base.ErrNotFound 39 ErrClosed = errors.New("bitalosdb: closed") 40 errMemExceedDelPercent = errors.New("memtable exceed delpercent") 41 ) 42 43 type Reader interface { 44 Get(key []byte) (value []byte, closer func(), err error) 45 NewIter(o *IterOptions) *Iterator 46 Close() error 47 } 48 49 type Writer interface { 50 Apply(batch *Batch, o *WriteOptions) error 51 ApplyBitower(batch *BatchBitower, o *WriteOptions) error 52 Delete(key []byte, o *WriteOptions) error 53 LogData(data []byte, index int, opts *WriteOptions) error 54 Set(key, value []byte, o *WriteOptions) error 55 PrefixDeleteKeySet(key []byte, o *WriteOptions) error 56 } 57 58 type DB struct { 59 dirname string 60 walDirname string 61 opts *Options 62 optspool *options.OptionsPool 63 cmp Compare 64 equal Equal 65 split Split 66 timeNow func() time.Time 67 compressor compress.Compressor 68 fileLock io.Closer 69 dataDir vfs.File 70 closed atomic.Bool 71 dbState *statemachine.DbStateMachine 72 taskWg sync.WaitGroup 73 taskClosed chan struct{} 74 memFlushTask *bitask.MemFlushTask 75 bpageTask *bitask.BitpageTask 76 bitowers [consts.DefaultBitowerNum]*Bitower 77 cache cache.ICache 78 meta *metaSet 79 flushedBitable atomic.Bool 80 flushMemTime atomic.Int64 81 } 82 83 var _ Reader = (*DB)(nil) 84 var _ Writer = (*DB)(nil) 85 86 func (d *DB) getBitowerIndexByKey(key []byte) int { 87 if len(key) > 0 { 88 slot := d.opts.KeyHashFunc(key) 89 return base.GetBitowerIndex(slot) 90 } 91 return 0 92 } 93 94 func (d *DB) getBitowerByKey(key []byte) *Bitower { 95 index := d.getBitowerIndexByKey(key) 96 return d.bitowers[index] 97 } 98 99 func (d *DB) checkBitowerIndex(index int) bool { 100 return index >= 0 && index < consts.DefaultBitowerNum 101 } 102 103 func (d *DB) Get(key []byte) ([]byte, func(), error) { 104 if d.IsClosed() { 105 return nil, nil, ErrClosed 106 } 107 108 index := d.getBitowerIndexByKey(key) 109 return d.bitowers[index].Get(key) 110 } 111 112 func (d *DB) Exist(key []byte) (bool, error) { 113 if d.IsClosed() { 114 return false, ErrClosed 115 } 116 117 index := d.getBitowerIndexByKey(key) 118 if exist := d.bitowers[index].Exist(key); !exist { 119 return false, ErrNotFound 120 } 121 return true, nil 122 } 123 124 func (d *DB) CheckKeySize(key []byte) error { 125 if len(key) > consts.MaxKeySize || len(key) == 0 { 126 return errors.New("invalid key size") 127 } 128 129 return nil 130 } 131 132 func (d *DB) Set(key, value []byte, opts *WriteOptions) error { 133 if err := d.CheckKeySize(key); err != nil { 134 return err 135 } 136 137 b := newBatchBitower(d) 138 _ = b.Set(key, value, opts) 139 if err := d.ApplyBitower(b, opts); err != nil { 140 return err 141 } 142 143 b.release() 144 return nil 145 } 146 147 func (d *DB) PrefixDeleteKeySet(key []byte, opts *WriteOptions) error { 148 if err := d.CheckKeySize(key); err != nil { 149 return err 150 } 151 152 b := newBatchBitower(d) 153 _ = b.PrefixDeleteKeySet(key, opts) 154 if err := d.ApplyBitower(b, opts); err != nil { 155 return err 156 } 157 158 b.release() 159 return nil 160 } 161 162 func (d *DB) Delete(key []byte, opts *WriteOptions) error { 163 b := newBatchBitower(d) 164 _ = b.Delete(key, opts) 165 if err := d.ApplyBitower(b, opts); err != nil { 166 return err 167 } 168 169 b.release() 170 return nil 171 } 172 173 func (d *DB) LogData(data []byte, index int, opts *WriteOptions) error { 174 b := newBatchBitowerByIndex(d, index) 175 _ = b.LogData(data, opts) 176 if err := d.ApplyBitower(b, opts); err != nil { 177 return err 178 } 179 180 b.release() 181 return nil 182 } 183 184 func (d *DB) ApplyBitower(batch *BatchBitower, opts *WriteOptions) error { 185 if d.IsClosed() { 186 return ErrClosed 187 } 188 189 if !batch.indexValid { 190 return errors.New("index invalid") 191 } 192 193 if atomic.LoadUint32(&batch.applied) != 0 { 194 return errors.New("batchBitower already applied") 195 } 196 197 if batch.db != nil && batch.db != d { 198 return errors.Errorf("batchBitower db mismatch: %p != %p", batch.db, d) 199 } 200 201 isSync := opts.GetSync() 202 if isSync && d.opts.DisableWAL { 203 return errors.New("WAL disabled sync unusable") 204 } 205 206 if batch.db == nil { 207 batch.refreshMemTableSize() 208 } 209 210 index := batch.index 211 if err := d.bitowers[index].commit.Commit(batch, isSync); err != nil { 212 return errors.Errorf("batch apply commit fail index:%d err:%s", index, err) 213 } 214 215 return nil 216 } 217 218 func (d *DB) Apply(batch *Batch, opts *WriteOptions) error { 219 if d.IsClosed() { 220 return ErrClosed 221 } 222 223 isSync := opts.GetSync() 224 if isSync && d.opts.DisableWAL { 225 return errors.New("WAL disabled sync unusable") 226 } 227 228 if batch.db != nil && batch.db != d { 229 return errors.Errorf("batch db mismatch: %p != %p", batch.db, d) 230 } 231 232 for i, tower := range batch.bitowers { 233 if tower == nil || atomic.LoadUint32(&tower.applied) != 0 { 234 continue 235 } 236 237 if tower.db == nil { 238 tower.refreshMemTableSize() 239 } 240 241 if err := d.bitowers[i].commit.Commit(tower, isSync); err != nil { 242 return errors.Errorf("batch apply commit fail index:%d err:%s", i, err) 243 } 244 } 245 246 return nil 247 } 248 249 type iterAlloc struct { 250 dbi Iterator 251 keyBuf []byte 252 prefixOrFullSeekKey []byte 253 merging mergingIter 254 mlevels [2]mergingIterLevel 255 } 256 257 var iterAllocPool = sync.Pool{ 258 New: func() interface{} { 259 return &iterAlloc{} 260 }, 261 } 262 263 func (d *DB) newBitowerIter(o *IterOptions) *Iterator { 264 if d.IsClosed() { 265 return nil 266 } 267 268 index := base.GetBitowerIndex(int(o.SlotId)) 269 bitower := d.bitowers[index] 270 rs := bitower.loadReadState() 271 seqNum := atomic.LoadUint64(&d.meta.atomic.visibleSeqNum) 272 buf := iterAllocPool.Get().(*iterAlloc) 273 dbi := &buf.dbi 274 *dbi = Iterator{ 275 alloc: buf, 276 cmp: d.cmp, 277 equal: d.equal, 278 iter: &buf.merging, 279 split: d.split, 280 keyBuf: buf.keyBuf, 281 prefixOrFullSeekKey: buf.prefixOrFullSeekKey, 282 seqNum: seqNum, 283 index: index, 284 bitower: bitower, 285 readState: rs, 286 readStates: nil, 287 } 288 if o != nil { 289 dbi.opts = *o 290 } 291 dbi.opts.Logger = d.opts.Logger 292 293 mlevels := buf.mlevels[:0] 294 numMergingLevels := 1 295 296 for i := len(rs.memtables) - 1; i >= 0; i-- { 297 mem := rs.memtables[i] 298 if logSeqNum := mem.logSeqNum; logSeqNum >= seqNum { 299 continue 300 } 301 numMergingLevels++ 302 } 303 304 btreeIters := bitower.newBitreeIter(&dbi.opts) 305 numMergingLevels += len(btreeIters) 306 307 if numMergingLevels > cap(mlevels) { 308 mlevels = make([]mergingIterLevel, 0, numMergingLevels) 309 } 310 311 for i := len(rs.memtables) - 1; i >= 0; i-- { 312 mem := rs.memtables[i] 313 if logSeqNum := mem.logSeqNum; logSeqNum >= seqNum { 314 continue 315 } 316 mlevels = append(mlevels, mergingIterLevel{ 317 iter: mem.newIter(&dbi.opts), 318 }) 319 } 320 321 for i := len(btreeIters) - 1; i >= 0; i-- { 322 mlevels = append(mlevels, mergingIterLevel{ 323 iter: btreeIters[i], 324 }) 325 } 326 327 buf.merging.init(&dbi.opts, dbi.cmp, mlevels...) 328 buf.merging.snapshot = seqNum 329 return dbi 330 } 331 332 func (d *DB) newAllBitowerIter(o *IterOptions) *Iterator { 333 if d.IsClosed() { 334 return nil 335 } 336 337 var mlevels []mergingIterLevel 338 seqNum := atomic.LoadUint64(&d.meta.atomic.visibleSeqNum) 339 buf := iterAllocPool.Get().(*iterAlloc) 340 dbi := &buf.dbi 341 *dbi = Iterator{ 342 alloc: buf, 343 cmp: d.cmp, 344 equal: d.equal, 345 iter: &buf.merging, 346 split: d.split, 347 keyBuf: buf.keyBuf, 348 prefixOrFullSeekKey: buf.prefixOrFullSeekKey, 349 seqNum: seqNum, 350 index: iterAllFlag, 351 bitower: nil, 352 readState: nil, 353 } 354 if o != nil { 355 dbi.opts = *o 356 } else { 357 dbi.opts = IterAll 358 } 359 dbi.opts.Logger = d.opts.Logger 360 dbi.readStates = make([]*readState, len(d.bitowers)) 361 for i := range d.bitowers { 362 dbi.readStates[i] = d.bitowers[i].loadReadState() 363 for j := len(dbi.readStates[i].memtables) - 1; j >= 0; j-- { 364 mem := dbi.readStates[i].memtables[j] 365 if logSeqNum := mem.logSeqNum; logSeqNum >= seqNum { 366 continue 367 } 368 mlevels = append(mlevels, mergingIterLevel{ 369 iter: mem.newIter(&dbi.opts), 370 }) 371 } 372 373 btreeIters := d.bitowers[i].newBitreeIter(&dbi.opts) 374 for k := len(btreeIters) - 1; k >= 0; k-- { 375 mlevels = append(mlevels, mergingIterLevel{ 376 iter: btreeIters[k], 377 }) 378 } 379 } 380 381 buf.merging.init(&dbi.opts, dbi.cmp, mlevels...) 382 buf.merging.snapshot = seqNum 383 return dbi 384 } 385 386 func (d *DB) NewIter(o *IterOptions) *Iterator { 387 if !o.IsGetAll() { 388 return d.newBitowerIter(o) 389 } else { 390 return d.newAllBitowerIter(o) 391 } 392 } 393 394 func (d *DB) NewBatch() *Batch { 395 return newBatch(d) 396 } 397 398 func (d *DB) NewBatchBitower() *BatchBitower { 399 return newBatchBitower(d) 400 } 401 402 func (d *DB) IsClosed() bool { 403 return d.closed.Load() 404 } 405 406 func (d *DB) closeTask() { 407 close(d.taskClosed) 408 d.memFlushTask.Close() 409 d.bpageTask.Close() 410 d.taskWg.Wait() 411 } 412 413 func (d *DB) Close() (err error) { 414 if d.IsClosed() { 415 return ErrClosed 416 } 417 418 d.opts.Logger.Infof("bitalosdb close start") 419 420 d.closed.Store(true) 421 422 defer func() { 423 if d.cache != nil { 424 d.cache.Close() 425 } 426 d.optspool.Close() 427 d.opts.Logger.Infof("bitalosdb close finish") 428 }() 429 430 d.closeTask() 431 432 for i := range d.bitowers { 433 err = utils.FirstError(err, d.bitowers[i].Close()) 434 } 435 436 err = utils.FirstError(err, d.meta.close()) 437 err = utils.FirstError(err, d.fileLock.Close()) 438 err = utils.FirstError(err, d.dataDir.Close()) 439 440 return err 441 } 442 443 func (d *DB) Flush() error { 444 g, _ := errgroup.WithContext(context.Background()) 445 for i := range d.bitowers { 446 index := i 447 g.Go(func() error { 448 return d.bitowers[index].Flush() 449 }) 450 } 451 return g.Wait() 452 } 453 454 func (d *DB) AsyncFlush() (<-chan struct{}, error) { 455 if d.IsClosed() { 456 return nil, ErrClosed 457 } 458 459 flushed := make(chan struct{}) 460 flusheds := make([]<-chan struct{}, 0, len(d.bitowers)) 461 462 for i := range d.bitowers { 463 ch, err := d.bitowers[i].AsyncFlush() 464 if err != nil { 465 return nil, err 466 } 467 if ch != nil { 468 flusheds = append(flusheds, ch) 469 } 470 } 471 472 if len(flusheds) == 0 { 473 return nil, nil 474 } 475 476 go func() { 477 for _, ch := range flusheds { 478 <-ch 479 } 480 close(flushed) 481 }() 482 483 return flushed, nil 484 } 485 486 func (d *DB) LockTask() { 487 d.dbState.LockTask() 488 } 489 490 func (d *DB) UnlockTask() { 491 d.dbState.UnlockTask() 492 } 493 494 func (d *DB) Id() int { 495 return d.opts.Id 496 } 497 498 func (d *DB) isFlushedBitable() bool { 499 if !d.opts.UseBitable { 500 return false 501 } 502 return d.flushedBitable.Load() 503 } 504 505 func (d *DB) setFlushedBitable() { 506 if !d.opts.UseBitable { 507 return 508 } 509 d.meta.meta.SetFieldFlushedBitable() 510 d.flushedBitable.Store(true) 511 } 512 513 func (d *DB) initFlushedBitable() { 514 if !d.opts.UseBitable { 515 return 516 } 517 flushedBitable := d.meta.meta.GetFieldFlushedBitable() 518 if flushedBitable == 1 { 519 d.flushedBitable.Store(true) 520 } else { 521 d.flushedBitable.Store(false) 522 } 523 }