github.com/zuoyebang/bitalosdb@v1.1.1-0.20240516111551-79a8c4d8ce20/bitree/bitable.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 "io" 19 "time" 20 21 "github.com/zuoyebang/bitalosdb/bitable" 22 "github.com/zuoyebang/bitalosdb/bitpage" 23 "github.com/zuoyebang/bitalosdb/internal/base" 24 "github.com/zuoyebang/bitalosdb/internal/consts" 25 "github.com/zuoyebang/bitalosdb/internal/options" 26 "github.com/zuoyebang/bitalosdb/internal/utils" 27 ) 28 29 func (t *Bitree) newBitableIter(o *options.IterOptions) *bitable.BitableIterator { 30 if t.btable == nil { 31 return nil 32 } 33 34 return t.btable.NewIter(o) 35 } 36 37 func (t *Bitree) bitableExist(key []byte) bool { 38 _, closer, err := t.bitableGet(key) 39 if closer != nil { 40 closer.Close() 41 } 42 43 return err != base.ErrNotFound 44 } 45 46 func (t *Bitree) bitableGet(key []byte) ([]byte, io.Closer, error) { 47 if t.btable == nil || !t.opts.IsFlushedBitableCB() { 48 return nil, nil, base.ErrNotFound 49 } 50 51 return t.btable.Get(key) 52 } 53 54 func (t *Bitree) bitableDelete(key []byte) error { 55 if t.btable == nil || !t.opts.IsFlushedBitableCB() { 56 return nil 57 } 58 59 val, closer, err := t.btable.Get(key) 60 if closer != nil { 61 _ = closer.Close() 62 } 63 if err == base.ErrNotFound { 64 return nil 65 } 66 67 t.DeleteBithashKey(val) 68 69 return t.btable.Delete(key) 70 } 71 72 func (t *Bitree) ManualCompact() error { 73 if t.btable == nil { 74 return nil 75 } 76 77 err := t.btable.Compact(nil, []byte{0xff, 0xff}, false) 78 return err 79 } 80 81 func (t *Bitree) CompactBitreeToBitable() (pn bitpage.PageNum) { 82 if t.btable == nil { 83 return 84 } 85 86 t.dbState.WaitBitowerHighPriority(t.index) 87 t.dbState.LockBitowerWrite(t.index) 88 defer t.dbState.UnlockBitowerWrite(t.index) 89 90 start := time.Now() 91 92 deleteBitable := func(batch *bitable.BitableBatch, key []byte) { 93 btVal, closer, btErr := t.bitableGet(key) 94 defer func() { 95 if closer != nil { 96 closer.Close() 97 } 98 }() 99 if btErr != base.ErrNotFound { 100 t.DeleteBithashKey(btVal) 101 _ = batch.Delete(key) 102 } 103 } 104 105 flushToBitable := func(ciMaxSize int) error { 106 t.btable.CloseAutomaticCompactions() 107 defer t.btable.OpenAutomaticCompactions() 108 109 iter := t.newBitreeIter(nil) 110 defer iter.Close() 111 112 iter.SetCompact() 113 ciFlushSize := ciMaxSize - 6<<20 114 var batch *bitable.BitableBatch 115 var err error 116 117 for k, v := iter.First(); k != nil; k, v = iter.Next() { 118 if batch == nil { 119 batch = t.btable.NewFlushBatch(ciMaxSize) 120 } 121 122 switch k.Kind() { 123 case base.InternalKeyKindSet: 124 if t.opts.BitpageOpts.CheckExpireCB(k.UserKey, v) { 125 deleteBitable(batch, k.UserKey) 126 } else { 127 _ = batch.Set(k.UserKey, v) 128 } 129 case base.InternalKeyKindDelete: 130 deleteBitable(batch, k.UserKey) 131 } 132 133 if batch.Size() > ciFlushSize { 134 if err = batch.Commit(); err != nil { 135 return err 136 } 137 _ = batch.Close() 138 batch = nil 139 } 140 141 if err != nil { 142 t.opts.Logger.Errorf("[COMPACTBITABLE %d] flushToBitable write fail err:%s", t.index, err) 143 err = nil 144 } 145 } 146 147 if batch == nil { 148 return nil 149 } 150 151 err = batch.Commit() 152 _ = batch.Close() 153 batch = nil 154 return err 155 } 156 157 if err := flushToBitable(consts.CompactToBitableCiMaxSize); err != nil { 158 t.opts.Logger.Errorf("[COMPACTBITABLE %d] flushToBitable fail err:%s", t.index, err) 159 return 160 } 161 162 resetBitree := func() error { 163 tx, err := t.bdb.Begin(true) 164 if err != nil { 165 return err 166 } 167 defer func() { 168 if err != nil { 169 _ = tx.Rollback() 170 } 171 }() 172 173 bkt := tx.Bucket(consts.BdbBucketName) 174 if bkt == nil { 175 err = ErrBucketNotExist 176 return err 177 } 178 179 it := t.NewBdbIter() 180 defer it.Close() 181 182 var pns []bitpage.PageNum 183 for k, v := it.First(); k != nil; k, v = it.Next() { 184 if err = bkt.Delete(k.UserKey); err != nil { 185 return err 186 } 187 pns = append(pns, bitpage.PageNum(utils.BytesToUint32(v))) 188 } 189 190 pn, err = t.bpage.NewPage() 191 if err != nil { 192 return err 193 } 194 defer func() { 195 if err != nil { 196 _ = t.bpage.FreePage(pn, false) 197 } 198 }() 199 200 if err = bkt.Put(consts.BdbMaxKey, pn.ToByte()); err != nil { 201 return err 202 } 203 204 if err = tx.Commit(); err != nil { 205 return err 206 } 207 208 t.bpage.MarkFreePages(pns) 209 return nil 210 } 211 212 if err := resetBitree(); err != nil { 213 pn = nilPageNum 214 t.opts.Logger.Errorf("[COMPACTBITABLE %d] bdbReset fail err:%s", t.index, err) 215 } 216 217 if !t.BdbUpdate() { 218 t.opts.Logger.Errorf("[COMPACTBITABLE %d] bdb txPool swaptx fail", t.index) 219 } 220 221 t.bpage.ResetStats() 222 t.opts.Logger.Infof("[COMPACTBITABLE %d] compact finish cost:%.3fs", t.index, time.Since(start).Seconds()) 223 224 return 225 } 226 227 func (t *Bitree) BitableDebugInfo(dataType string) string { 228 if t.btable == nil || !t.opts.IsFlushedBitableCB() { 229 return "" 230 } 231 return t.btable.DebugInfo(dataType) 232 }