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  }