github.com/zuoyebang/bitalosdb@v1.1.1-0.20240516111551-79a8c4d8ce20/bitree/writer.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  	"encoding/binary"
    19  
    20  	"github.com/cockroachdb/errors"
    21  	"github.com/zuoyebang/bitalosdb/bithash"
    22  	"github.com/zuoyebang/bitalosdb/bitpage"
    23  	"github.com/zuoyebang/bitalosdb/bitree/bdb"
    24  	"github.com/zuoyebang/bitalosdb/internal/base"
    25  	"github.com/zuoyebang/bitalosdb/internal/bitask"
    26  )
    27  
    28  type BitreeWriter struct {
    29  	btree       *Bitree
    30  	bdbReadTx   *bdb.ReadTx
    31  	bdbCursor   *bdb.Cursor
    32  	bhashWriter *bithash.BithashWriter
    33  	bpageWriter map[bitpage.PageNum]*bitpage.PageWriter
    34  }
    35  
    36  func (w *BitreeWriter) getBitpageWriter(pn bitpage.PageNum, sentinel []byte) *bitpage.PageWriter {
    37  	pageWriter, ok := w.bpageWriter[pn]
    38  	if ok {
    39  		return pageWriter
    40  	}
    41  
    42  	writer := w.btree.bpage.GetPageWriter(pn, sentinel)
    43  	if writer == nil {
    44  		return nil
    45  	}
    46  
    47  	w.bpageWriter[pn] = writer
    48  	return writer
    49  }
    50  
    51  func (w *BitreeWriter) set(key base.InternalKey, value []byte, pn bitpage.PageNum, sentinel []byte) (err error) {
    52  	pageWriter := w.getBitpageWriter(pn, sentinel)
    53  	if pageWriter == nil {
    54  		return errors.Errorf("bitree: getBitpageWriter nil index:%d pageNum:%s", w.btree.index, pn)
    55  	}
    56  
    57  	switch key.Kind() {
    58  	case base.InternalKeyKindSet:
    59  		keySeqNum := key.SeqNum()
    60  		if w.btree.IsKvSeparate(len(value)) {
    61  			keyFileNum, err := w.bhashWriter.Add(key, value)
    62  			if err != nil {
    63  				return err
    64  			}
    65  
    66  			isExistTm, tm := w.btree.opts.KvTimestampFunc(value, 1)
    67  			if isExistTm {
    68  				var ev [20]byte
    69  				binary.LittleEndian.PutUint64(ev[0:8], (keySeqNum<<8)|uint64(base.InternalKeyKindSetBithash))
    70  				binary.LittleEndian.PutUint32(ev[8:12], uint32(keyFileNum))
    71  				binary.LittleEndian.PutUint64(ev[12:20], tm)
    72  				err = pageWriter.Set(key, ev[:])
    73  			} else {
    74  				var ev [12]byte
    75  				binary.LittleEndian.PutUint64(ev[0:8], (keySeqNum<<8)|uint64(base.InternalKeyKindSetBithash))
    76  				binary.LittleEndian.PutUint32(ev[8:12], uint32(keyFileNum))
    77  				err = pageWriter.Set(key, ev[:])
    78  			}
    79  		} else {
    80  			ev, evCloser := base.EncodeInternalValue(value, keySeqNum, base.InternalKeyKindSet)
    81  			err = pageWriter.Set(key, ev)
    82  			evCloser()
    83  		}
    84  	case base.InternalKeyKindDelete, base.InternalKeyKindPrefixDelete:
    85  		err = pageWriter.Set(key, nil)
    86  	}
    87  
    88  	return err
    89  }
    90  
    91  func (w *BitreeWriter) Apply(key base.InternalKey, value []byte) error {
    92  	kind := key.Kind()
    93  	if kind != base.InternalKeyKindPrefixDelete {
    94  		pn, sentinel := w.btree.findKeyPageNum(key.UserKey, w.bdbCursor)
    95  		if pn == nilPageNum {
    96  			return errors.New("findKeyPageNum nil")
    97  		}
    98  
    99  		if err := w.set(key, value, pn, sentinel); err != nil {
   100  			return err
   101  		}
   102  	} else {
   103  		pns, sentinels := w.btree.findPrefixDeleteKeyPageNums(key.UserKey, w.bdbCursor)
   104  		if len(pns) == 0 || len(sentinels) == 0 {
   105  			return errors.New("findPrefixDeleteKeyPageNums nil")
   106  		}
   107  
   108  		for j := range pns {
   109  			if err := w.set(key, value, pns[j], sentinels[j]); err != nil {
   110  				continue
   111  			}
   112  		}
   113  	}
   114  
   115  	return nil
   116  }
   117  
   118  func (w *BitreeWriter) RefBdbTx() {
   119  	if w.bdbReadTx == nil {
   120  		w.bdbReadTx = w.btree.txPool.Load()
   121  		w.bdbCursor = w.bdbReadTx.Bucket().Cursor()
   122  	}
   123  }
   124  
   125  func (w *BitreeWriter) UnrefBdbTx() {
   126  	if w.bdbReadTx != nil {
   127  		w.bdbReadTx.Unref(true)
   128  		w.bdbReadTx = nil
   129  	}
   130  }
   131  
   132  func (w *BitreeWriter) Finish() error {
   133  	w.UnrefBdbTx()
   134  
   135  	if w.bhashWriter != nil {
   136  		if err := w.btree.bhash.FlushFinish(w.bhashWriter); err != nil {
   137  			return err
   138  		}
   139  		w.bhashWriter = nil
   140  	}
   141  
   142  	flushSize := w.btree.opts.BitpageFlushSize
   143  
   144  	for pn, pageWriter := range w.bpageWriter {
   145  		if err := pageWriter.FlushFinish(); err != nil {
   146  			w.btree.opts.Logger.Errorf("bitree pageWriter FlushFinish fail pn:%d err:%s", pn, err)
   147  			continue
   148  		}
   149  		pageWriter.UpdateMetaTimestamp()
   150  		if pageWriter.MaybePageFlush(flushSize) {
   151  			w.btree.opts.BitpageTaskPushFunc(&bitask.BitpageTaskData{
   152  				Index:    w.btree.index,
   153  				Event:    bitask.BitpageEventFlush,
   154  				Pn:       uint32(pn),
   155  				Sentinel: pageWriter.Sentinel,
   156  			})
   157  		}
   158  	}
   159  
   160  	w.bpageWriter = nil
   161  	return nil
   162  }
   163  
   164  func (t *Bitree) NewBitreeWriter() (*BitreeWriter, error) {
   165  	writer := &BitreeWriter{
   166  		btree: t,
   167  	}
   168  
   169  	if t.opts.UseBithash {
   170  		w, err := t.bhash.FlushStart()
   171  		if err != nil {
   172  			return nil, err
   173  		}
   174  		writer.bhashWriter = w
   175  	}
   176  
   177  	writer.RefBdbTx()
   178  	writer.bpageWriter = make(map[bitpage.PageNum]*bitpage.PageWriter, 16)
   179  
   180  	return writer, nil
   181  }