github.com/zuoyebang/bitalosdb@v1.1.1-0.20240516111551-79a8c4d8ce20/bitree/bdb_test.go (about) 1 package bitree 2 3 import ( 4 "fmt" 5 "os" 6 "testing" 7 8 "github.com/stretchr/testify/require" 9 "github.com/zuoyebang/bitalosdb/bitpage" 10 "github.com/zuoyebang/bitalosdb/bitree/bdb" 11 "github.com/zuoyebang/bitalosdb/internal/consts" 12 "github.com/zuoyebang/bitalosdb/internal/sortedkv" 13 "github.com/zuoyebang/bitalosdb/internal/utils" 14 ) 15 16 func TestBitree_Bdb_Seek(t *testing.T) { 17 defer os.RemoveAll(testDir) 18 os.RemoveAll(testDir) 19 20 seekFunc := func(index int) { 21 btree, _ := testOpenBitree() 22 23 pn, sentinel, closer := btree.FindKeyPageNum(consts.BdbMaxKey) 24 require.Equal(t, bitpage.PageNum(1), pn) 25 require.Equal(t, consts.BdbMaxKey, sentinel) 26 closer() 27 28 if index == 0 { 29 for i := 0; i < 10; i++ { 30 key := makeTestKey(i) 31 pn, sentinel, closer = btree.FindKeyPageNum(key) 32 require.Equal(t, bitpage.PageNum(1), pn) 33 require.Equal(t, consts.BdbMaxKey, sentinel) 34 closer() 35 } 36 err := btree.bdb.Update(func(tx *bdb.Tx) error { 37 bkt := tx.Bucket(consts.BdbBucketName) 38 if bkt == nil { 39 return bdb.ErrBucketNotFound 40 } 41 for i := 2; i < 10; i++ { 42 if i%3 != 0 { 43 continue 44 } 45 46 key := makeTestKey(i) 47 require.NoError(t, bkt.Put(key, bitpage.PageNum(i).ToByte())) 48 } 49 return nil 50 }) 51 btree.txPool.Update() 52 require.NoError(t, err) 53 } 54 55 checkValue := func(i, exp int) { 56 key := makeTestKey(i) 57 pn, sentinel, closer = btree.FindKeyPageNum(key) 58 require.Equal(t, bitpage.PageNum(exp), pn) 59 closer() 60 if exp == 1 { 61 require.Equal(t, consts.BdbMaxKey, sentinel) 62 } else { 63 require.Equal(t, makeTestKey(exp), sentinel) 64 } 65 } 66 67 checkValue(0, 3) 68 checkValue(3, 3) 69 checkValue(12, 3) 70 checkValue(4, 6) 71 checkValue(5, 6) 72 checkValue(51, 6) 73 checkValue(6, 6) 74 checkValue(60, 9) 75 checkValue(899, 9) 76 checkValue(9, 9) 77 checkValue(90, 1) 78 checkValue(91, 1) 79 80 require.NoError(t, testBitreeClose(btree)) 81 } 82 83 for i := 0; i < 5; i++ { 84 seekFunc(i) 85 } 86 } 87 88 func TestBitree_Bdb_Seek_LargeKey(t *testing.T) { 89 defer os.RemoveAll(testDir) 90 os.RemoveAll(testDir) 91 92 btree, _ := testOpenBitree() 93 keyPrefix := utils.FuncRandBytes(1100) 94 makeLargeKey := func(i int) []byte { 95 return []byte(fmt.Sprintf("bdb_%s_%d", keyPrefix, i)) 96 } 97 err := btree.bdb.Update(func(tx *bdb.Tx) error { 98 bkt := tx.Bucket(consts.BdbBucketName) 99 if bkt == nil { 100 return bdb.ErrBucketNotFound 101 } 102 for i := 2; i < 200; i++ { 103 if i%3 != 0 { 104 continue 105 } 106 key := makeLargeKey(i) 107 require.NoError(t, bkt.Put(key, bitpage.PageNum(i).ToByte())) 108 } 109 return nil 110 }) 111 btree.txPool.Update() 112 require.NoError(t, err) 113 114 expPns := []int{102, 102, 21, 3, 42, 51, 6, 72, 81, 9, 102, 111, 12, 132, 141, 15, 162, 171, 18, 192, 21, 21, 24, 24, 115 24, 27, 27, 27, 3, 3, 30, 33, 33, 33, 36, 36, 36, 39, 39, 39, 42, 42, 42, 45, 45, 45, 48, 48, 48, 51, 51, 51, 54, 54, 54, 116 57, 57, 57, 6, 6, 60, 63, 63, 63, 66, 66, 66, 69, 69, 69, 72, 72, 72, 75, 75, 75, 78, 78, 78, 81, 81, 81, 84, 84, 84, 87, 117 87, 87, 9, 9, 90, 93, 93, 93, 96, 96, 96, 99, 99, 99, 102, 102, 102, 105, 105, 105, 108, 108, 108, 111, 111, 111, 114, 118 114, 114, 117, 117, 117, 12, 12, 120, 123, 123, 123, 126, 126, 126, 129, 129, 129, 132, 132, 132, 135, 135, 135, 119 138, 138, 138, 141, 141, 141, 144, 144, 144, 147, 147, 147, 15, 15, 150, 153, 153, 153, 156, 156, 156, 159, 159, 120 159, 162, 162, 162, 165, 165, 165, 168, 168, 168, 171, 171, 171, 174, 174, 174, 177, 177, 177, 18, 18, 180, 183, 121 183, 183, 186, 186, 186, 189, 189, 189, 192, 192, 192, 195, 195, 195, 198, 198, 198, 21} 122 123 for i := 0; i < 200; i++ { 124 key := makeLargeKey(i) 125 pn, _, closer := btree.FindKeyPageNum(key) 126 require.Equal(t, bitpage.PageNum(expPns[i]), pn) 127 closer() 128 } 129 130 checkValue := func(i, exp int) { 131 key := makeLargeKey(i) 132 pn, sentinel, closer := btree.FindKeyPageNum(key) 133 require.Equal(t, bitpage.PageNum(exp), pn) 134 closer() 135 if exp == 1 { 136 require.Equal(t, consts.BdbMaxKey, sentinel) 137 } else { 138 require.Equal(t, makeLargeKey(exp), sentinel) 139 } 140 } 141 142 checkValue(201, 21) 143 checkValue(255, 27) 144 checkValue(402, 42) 145 checkValue(518, 54) 146 checkValue(627, 63) 147 checkValue(734, 75) 148 checkValue(846, 87) 149 checkValue(899, 9) 150 checkValue(953, 96) 151 checkValue(999, 1) 152 153 require.NoError(t, testBitreeClose(btree)) 154 } 155 156 func TestBitree_Bdb_SeekPrefixDeleteKey(t *testing.T) { 157 for _, isLarge := range []bool{false, true} { 158 t.Run(fmt.Sprintf("isLarge=%t", isLarge), func(t *testing.T) { 159 defer os.RemoveAll(testDir) 160 os.RemoveAll(testDir) 161 162 btree, _ := testOpenBitree() 163 defer testBitreeClose(btree) 164 165 var keyPrefix, largePrefix []byte 166 slotId := uint16(1) 167 verNum := 5 168 verStart := uint64(1024) 169 verEnd := uint64(1030) 170 if isLarge { 171 largePrefix = utils.FuncRandBytes(1100) 172 } else { 173 largePrefix = []byte("") 174 } 175 176 makeKey := func(n int, v uint64) []byte { 177 keyPrefix = []byte(fmt.Sprintf("bdb_%s_%d", largePrefix, n)) 178 return sortedkv.MakeKey2(keyPrefix, slotId, v) 179 } 180 181 err := btree.bdb.Update(func(tx *bdb.Tx) error { 182 bkt := tx.Bucket(consts.BdbBucketName) 183 if bkt == nil { 184 return bdb.ErrBucketNotFound 185 } 186 187 for ver := verStart; ver <= verEnd; ver++ { 188 for i := 1; i <= verNum; i++ { 189 key := makeKey(i, ver) 190 require.NoError(t, bkt.Put(key, bitpage.PageNum(i).ToByte())) 191 } 192 } 193 return nil 194 }) 195 btree.txPool.Update() 196 require.NoError(t, err) 197 198 checkSeek := func(n int, version uint64) { 199 rtx := btree.txPool.Load() 200 defer rtx.Unref(true) 201 202 bkt := rtx.Bucket() 203 if bkt == nil { 204 t.Fatal("bkt is nil") 205 } 206 207 seek := makeKey(n, version) 208 pns, sentinels := btree.findPrefixDeleteKeyPageNums(seek, bkt.Cursor()) 209 210 if version > verEnd { 211 require.Equal(t, 1, len(pns)) 212 require.Equal(t, 1, len(sentinels)) 213 require.Equal(t, consts.BdbMaxKey, sentinels[0]) 214 return 215 } 216 217 expNum := verNum - n + 2 218 sentinelsNum := len(sentinels) 219 require.Equal(t, expNum, len(pns)) 220 require.Equal(t, expNum, sentinelsNum) 221 222 seekPrefixDelete := btree.opts.KeyPrefixDeleteFunc(seek) 223 for i := range sentinels { 224 s := btree.opts.KeyPrefixDeleteFunc(sentinels[i]) 225 exp := seekPrefixDelete 226 if i == sentinelsNum-1 { 227 if version == verEnd { 228 require.Equal(t, consts.BdbMaxKey, sentinels[i]) 229 break 230 } 231 exp = seekPrefixDelete + 1 232 } 233 require.Equal(t, exp, s) 234 } 235 } 236 237 for ver := verStart; ver <= verEnd+5; ver++ { 238 for i := 1; i <= verNum; i++ { 239 checkSeek(i, ver) 240 } 241 } 242 }) 243 } 244 }