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 }