github.com/zuoyebang/bitalosdb@v1.1.1-0.20240516111551-79a8c4d8ce20/bitree/bitpage.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  	"fmt"
    19  
    20  	"github.com/zuoyebang/bitalosdb/bitpage"
    21  	"github.com/zuoyebang/bitalosdb/bitree/bdb"
    22  	"github.com/zuoyebang/bitalosdb/internal/base"
    23  	"github.com/zuoyebang/bitalosdb/internal/bitask"
    24  	"github.com/zuoyebang/bitalosdb/internal/consts"
    25  	"github.com/zuoyebang/bitalosdb/internal/options"
    26  )
    27  
    28  const nilPageNum bitpage.PageNum = 0
    29  
    30  func (t *Bitree) BitpageStats() *bitpage.Stats {
    31  	return t.bpage.Stats()
    32  }
    33  
    34  func (t *Bitree) newPageIter(pn bitpage.PageNum, o *options.IterOptions) *bitpage.PageIterator {
    35  	return t.bpage.NewIter(pn, o)
    36  }
    37  
    38  func (t *Bitree) bitpageGet(key []byte, khash uint32) ([]byte, bool, func(), base.InternalKeyKind) {
    39  	pn, _, rtxCloser := t.FindKeyPageNum(key)
    40  	defer rtxCloser()
    41  	if pn == nilPageNum {
    42  		return nil, false, nil, base.InternalKeyKindInvalid
    43  	}
    44  
    45  	return t.bpage.Get(pn, key, khash)
    46  }
    47  
    48  func (t *Bitree) DoBitpageTask(task *bitask.BitpageTaskData) {
    49  	switch task.Event {
    50  	case bitask.BitpageEventFlush:
    51  		t.bitpageTaskFlush(task)
    52  	case bitask.BitpageEventSplit:
    53  		t.bitpageTaskSplit(task)
    54  	case bitask.BitpageEventFreePage:
    55  		t.bitpageTaskFreePage(task)
    56  	}
    57  
    58  	watiCh := task.WaitDuration.Seconds()
    59  	eventName := bitask.GetBitpageEventName(task.Event)
    60  
    61  	if len(task.Pns) == 0 {
    62  		t.opts.Logger.Infof("[BITPAGE %d] doTask finish event:%s pn:%d waitCh:%.3fs",
    63  			t.index, eventName, task.Pn, watiCh)
    64  	} else {
    65  		t.opts.Logger.Infof("[BITPAGE %d] doTask finish event:%s pns:%v waitCh:%.3fs",
    66  			t.index, eventName, task.Pns, watiCh)
    67  	}
    68  }
    69  
    70  func (t *Bitree) bitpageTaskFlush(task *bitask.BitpageTaskData) {
    71  	logTag := fmt.Sprintf("[BITPAGE %d] flush page(%d)", t.index, task.Pn)
    72  
    73  	t.dbState.LockBitowerWrite(t.index)
    74  	defer t.dbState.UnlockBitowerWrite(t.index)
    75  
    76  	if err := t.bpage.PageFlush(bitpage.PageNum(task.Pn), task.Sentinel, logTag); err != nil {
    77  		t.opts.Logger.Errorf("%s flush fail err:%s", logTag, err.Error())
    78  		return
    79  	}
    80  
    81  	t.dbState.AddBitpageFlushCount()
    82  }
    83  
    84  func (t *Bitree) bitpageTaskSplit(task *bitask.BitpageTaskData) {
    85  	logTag := fmt.Sprintf("[BITPAGE %d] split page(%d)", t.index, task.Pn)
    86  
    87  	t.dbState.LockBitowerWrite(t.index)
    88  	defer t.dbState.UnlockBitowerWrite(t.index)
    89  
    90  	if task.Sentinel == nil {
    91  		t.opts.Logger.Errorf("%s split fail sentinel key is nil", logTag)
    92  		return
    93  	}
    94  
    95  	sps, err := t.bpage.PageSplitStart(bitpage.PageNum(task.Pn), logTag)
    96  	if err == nil {
    97  		err = t.bdb.Update(func(tx *bdb.Tx) error {
    98  			bkt := tx.Bucket(consts.BdbBucketName)
    99  			if bkt == nil {
   100  				return bdb.ErrBucketNotFound
   101  			}
   102  
   103  			last := len(sps) - 1
   104  			for i := 0; i < last; i++ {
   105  				if err = bkt.Put(sps[i].Sentinel, sps[i].Pn.ToByte()); err != nil {
   106  					return err
   107  				}
   108  			}
   109  			if err = bkt.Put(task.Sentinel, sps[last].Pn.ToByte()); err != nil {
   110  				return err
   111  			}
   112  			return nil
   113  		})
   114  	}
   115  	t.bpage.PageSplitEnd(bitpage.PageNum(task.Pn), sps, err)
   116  
   117  	if err != nil {
   118  		t.opts.Logger.Errorf("%s split fail err:%s", logTag, err.Error())
   119  		return
   120  	}
   121  
   122  	t.dbState.AddBitpageSplitCount()
   123  
   124  	if !t.BdbUpdate() {
   125  		t.opts.Logger.Errorf("%s bdb txPool swaptx fail", logTag)
   126  	}
   127  
   128  	t.opts.Logger.Infof("%s split success spsNum:%d", logTag, len(sps))
   129  }
   130  
   131  func (t *Bitree) bitpageTaskFreePage(task *bitask.BitpageTaskData) {
   132  	if len(task.Pns) == 0 {
   133  		return
   134  	}
   135  
   136  	for _, pn := range task.Pns {
   137  		if err := t.bpage.FreePage(bitpage.PageNum(pn), true); err != nil {
   138  			if err == bitpage.ErrPageNotSplitted {
   139  				t.opts.Logger.Errorf("[BITPAGE %d] free page(%d) skip not splitted", t.index, pn)
   140  			} else {
   141  				t.opts.Logger.Errorf("[BITPAGE %d] free page(%d) fail err:%s", t.index, pn, err)
   142  			}
   143  		} else {
   144  			t.opts.Logger.Infof("[BITPAGE %d] free page(%d) done", t.index, pn)
   145  		}
   146  	}
   147  }
   148  
   149  func (t *Bitree) checkPageSplitted(pn uint32) bool {
   150  	return t.bpage.PageSplitted2(bitpage.PageNum(pn))
   151  }
   152  
   153  func (t *Bitree) GetGetNeedFlushBitPageNums(isForce bool) []bitpage.PageNum {
   154  	return t.bpage.GetNeedFlushPageNums(isForce)
   155  }
   156  
   157  func (t *Bitree) MaybeScheduleFlush(isForce bool) {
   158  	pns := t.bpage.GetNeedFlushPageNums(isForce)
   159  	if len(pns) == 0 {
   160  		return
   161  	}
   162  
   163  	for i := range pns {
   164  		t.opts.BitpageTaskPushFunc(&bitask.BitpageTaskData{
   165  			Index:    t.index,
   166  			Event:    bitask.BitpageEventFlush,
   167  			Pn:       uint32(pns[i]),
   168  			Sentinel: nil,
   169  		})
   170  	}
   171  
   172  	t.opts.Logger.Infof("[BITPAGE %d] manualScheduleFlush pns:%v", t.index, pns)
   173  }