github.com/zuoyebang/bitalosdb@v1.1.1-0.20240516111551-79a8c4d8ce20/bitpage/compaction_test.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 bitpage 16 17 import ( 18 "fmt" 19 "os" 20 "testing" 21 22 "github.com/stretchr/testify/require" 23 "github.com/zuoyebang/bitalosdb/internal/base" 24 "github.com/zuoyebang/bitalosdb/internal/hash" 25 "github.com/zuoyebang/bitalosdb/internal/sortedkv" 26 "github.com/zuoyebang/bitalosdb/internal/utils" 27 ) 28 29 func TestBitpageCompact_Flush(t *testing.T) { 30 testcase(func(index int, params []bool) { 31 dir := testDir 32 defer os.RemoveAll(dir) 33 os.RemoveAll(dir) 34 35 var endIndex int 36 num := 10 37 stepCount := 10 38 seqNum := uint64(1) 39 count := (num + 2) * stepCount 40 kvList := testMakeSortedKV(count, seqNum, 10) 41 seqNum += uint64(count) 42 43 writeData := func(bp *Bitpage, pn PageNum) { 44 wr := bp.GetPageWriter(pn, nil) 45 46 startIndex := endIndex 47 endIndex = startIndex + stepCount 48 49 for i := startIndex; i < endIndex; i++ { 50 if i%3 == 0 { 51 kvList[i].Key.SetKind(internalKeyKindDelete) 52 kvList[i].Value = []byte{} 53 } 54 require.NoError(t, wr.Set(*kvList[i].Key, kvList[i].Value)) 55 } 56 require.NoError(t, wr.FlushFinish()) 57 } 58 59 readData := func(pg *page) { 60 for i := 0; i < endIndex; i++ { 61 key := kvList[i].Key.UserKey 62 v, vexist, vcloser, kind := pg.get(key, hash.Crc32(key)) 63 if i%3 == 0 { 64 require.Equal(t, false, vexist) 65 } else { 66 require.Equal(t, kvList[i].Value, v) 67 require.Equal(t, internalKeyKindSet, kind) 68 vcloser() 69 } 70 } 71 } 72 73 bp, err := testOpenBitpage(true) 74 require.NoError(t, err) 75 pn, err1 := bp.NewPage() 76 require.NoError(t, err1) 77 78 writeData(bp, pn) 79 p := bp.GetPage(pn) 80 81 iter := p.newIter(nil) 82 require.NoError(t, p.flush(nil, "")) 83 require.NoError(t, iter.Close()) 84 85 writeData(bp, pn) 86 readData(p) 87 testCloseBitpage(t, bp) 88 89 for i := 0; i < num; i++ { 90 fmt.Println("for start", i) 91 bp2, err2 := testOpenBitpage(true) 92 require.NoError(t, err2) 93 writeData(bp2, pn) 94 p2 := bp2.GetPage(pn) 95 require.NoError(t, p2.flush(nil, "")) 96 readData(bp2.GetPage(pn)) 97 testCloseBitpage(t, bp2) 98 } 99 }) 100 } 101 102 func TestBitpageCompact_Flush_TableFull(t *testing.T) { 103 testcase(func(index int, params []bool) { 104 dir := testDir 105 defer os.RemoveAll(dir) 106 os.RemoveAll(dir) 107 108 var endIndex int 109 stepCount := 15000 110 seqNum := uint64(1) 111 count := 2 * stepCount 112 kvList := testMakeSortedKV(count, seqNum, 100) 113 seqNum += uint64(count) 114 115 writeData := func(bp *Bitpage, pn PageNum) { 116 wr := bp.GetPageWriter(pn, nil) 117 118 startIndex := endIndex 119 endIndex = startIndex + stepCount 120 for i := startIndex; i < endIndex; i++ { 121 if i%3 == 0 { 122 kvList[i].Key.SetKind(internalKeyKindDelete) 123 kvList[i].Value = []byte{} 124 } 125 require.NoError(t, wr.Set(*kvList[i].Key, kvList[i].Value)) 126 } 127 require.NoError(t, wr.FlushFinish()) 128 require.Equal(t, true, wr.MaybePageFlush(1<<20)) 129 } 130 131 readData := func(pg *page) { 132 for i := 0; i < endIndex; i++ { 133 key := kvList[i].Key.UserKey 134 v, vexist, vcloser, kind := pg.get(key, hash.Crc32(key)) 135 if i%3 == 0 { 136 require.Equal(t, false, vexist) 137 } else { 138 require.Equal(t, kvList[i].Value, v) 139 require.Equal(t, internalKeyKindSet, kind) 140 vcloser() 141 } 142 } 143 } 144 145 bp, err := testOpenBitpage(true) 146 require.NoError(t, err) 147 pn, err1 := bp.NewPage() 148 require.NoError(t, err1) 149 p := bp.GetPage(pn) 150 151 require.Equal(t, 1, len(p.mu.stQueue)) 152 writeData(bp, pn) 153 require.NoError(t, p.flush(nil, "")) 154 require.Equal(t, 1, len(p.mu.stQueue)) 155 require.Equal(t, pageFlushStateFinish, p.getFlushState()) 156 p.setFlushState(pageFlushStateNone) 157 writeData(bp, pn) 158 require.NoError(t, p.flush(nil, "")) 159 require.Equal(t, 1, len(p.mu.stQueue)) 160 require.Equal(t, pageFlushStateFinish, p.getFlushState()) 161 readData(p) 162 testCloseBitpage(t, bp) 163 164 bp1, err2 := testOpenBitpage(true) 165 require.NoError(t, err2) 166 p1 := bp1.GetPage(pn) 167 readData(p1) 168 testCloseBitpage(t, bp1) 169 }) 170 } 171 172 func TestBitpageCompact_Split(t *testing.T) { 173 testcase(func(index int, params []bool) { 174 dir := testDir 175 defer os.RemoveAll(dir) 176 os.RemoveAll(dir) 177 178 bp, err := testOpenBitpage2(dir, params[0], params[1], params[2]) 179 require.NoError(t, err) 180 pn, err1 := bp.NewPage() 181 require.NoError(t, err1) 182 183 seqNum := uint64(1) 184 count := 50000 185 kvList := testMakeSortedKV(count, seqNum, 100) 186 seqNum += uint64(count) 187 wr := bp.GetPageWriter(pn, nil) 188 189 for i := 0; i < count; i++ { 190 require.NoError(t, wr.Set(*kvList[i].Key, kvList[i].Value)) 191 } 192 require.NoError(t, wr.FlushFinish()) 193 194 p := bp.GetPage(pn) 195 require.NoError(t, p.flush(nil, "")) 196 197 bp.opts.BitpageSplitSize = 1 << 18 198 sps, err2 := bp.PageSplitStart(pn, "test") 199 require.NoError(t, err2) 200 bp.PageSplitEnd(pn, sps, nil) 201 202 spsPn := 2 203 for i := range sps { 204 require.Equal(t, PageNum(spsPn), sps[i].Pn) 205 spsPn++ 206 fmt.Println("sp:", i, spsPn, string(sps[i].Sentinel)) 207 } 208 209 pfiles := p.getFilesPath() 210 require.NoError(t, bp.FreePage(pn, true)) 211 bp.opts.DeleteFilePacer.Flush() 212 for i := range pfiles { 213 if utils.IsFileExist(pfiles[i]) { 214 t.Fatalf("%s is not delete", pfiles[i]) 215 } 216 } 217 218 testCloseBitpage(t, bp) 219 }) 220 } 221 222 func TestBitpageCompact_FlushArrayTableEmpty(t *testing.T) { 223 testcase(func(index int, params []bool) { 224 dir := testDir 225 defer os.RemoveAll(dir) 226 os.RemoveAll(dir) 227 228 bp, err := testOpenBitpage(true) 229 require.NoError(t, err) 230 pn, err1 := bp.NewPage() 231 require.NoError(t, err1) 232 233 seqNum := uint64(1) 234 count := 100 235 kvList := testMakeSortedKV(count, seqNum, 10) 236 seqNum += uint64(count) 237 wr := bp.GetPageWriter(pn, nil) 238 239 for i := 0; i < 100; i++ { 240 require.NoError(t, wr.Set(*kvList[i].Key, kvList[i].Value)) 241 } 242 require.NoError(t, wr.FlushFinish()) 243 244 p := bp.GetPage(pn) 245 246 require.NoError(t, p.flush(nil, "111")) 247 248 wr = bp.GetPageWriter(pn, nil) 249 for i := 0; i < 100; i++ { 250 kvList[i].Key.SetKind(internalKeyKindDelete) 251 kvList[i].Key.SetSeqNum(seqNum) 252 seqNum++ 253 require.NoError(t, wr.Set(*kvList[i].Key, kvList[i].Value)) 254 } 255 require.NoError(t, wr.FlushFinish()) 256 257 require.NoError(t, p.flush(nil, "222")) 258 if p.mu.arrtable != nil { 259 t.Fatal("arrtable is not nil") 260 } 261 262 for i := 0; i < 100; i++ { 263 key := makeTestKey(i) 264 _, vexist, vcloser, _ := p.get(key, hash.Crc32(key)) 265 require.Equal(t, false, vexist) 266 if vcloser != nil { 267 vcloser() 268 } 269 } 270 271 wr = bp.GetPageWriter(pn, nil) 272 for i := 0; i < 100; i++ { 273 kvList[i].Key.SetKind(internalKeyKindSet) 274 kvList[i].Key.SetSeqNum(seqNum) 275 seqNum++ 276 require.NoError(t, wr.Set(*kvList[i].Key, kvList[i].Value)) 277 } 278 require.NoError(t, wr.FlushFinish()) 279 280 require.NoError(t, p.flush(nil, "333")) 281 282 for i := 0; i < 100; i++ { 283 key := kvList[i].Key.UserKey 284 v, vexist, vcloser, kind := p.get(key, hash.Crc32(key)) 285 require.Equal(t, kvList[i].Value, v) 286 require.Equal(t, true, vexist) 287 require.Equal(t, internalKeyKindSet, kind) 288 vcloser() 289 } 290 291 testCloseBitpage(t, bp) 292 }) 293 } 294 295 func TestBitpageCompact_PrefixDeleteKey(t *testing.T) { 296 testcase(func(index int, params []bool) { 297 dir := testDir 298 defer os.RemoveAll(dir) 299 os.RemoveAll(dir) 300 301 var endIndex int 302 num := 5 303 stepCount := 30 304 seqNum := uint64(1) 305 count := (num + 2) * stepCount 306 kvList := sortedkv.MakeSortedSamePrefixDeleteKVList(0, count, seqNum, 10, testSlotId) 307 seqNum += uint64(count) 308 309 writeData := func(bp *Bitpage, pn PageNum) { 310 wr := bp.GetPageWriter(pn, nil) 311 startIndex := endIndex 312 endIndex = startIndex + stepCount 313 for i := startIndex; i < endIndex; i++ { 314 if i%3 == 0 && kvList[i].Key.Kind() != internalKeyKindPrefixDelete { 315 kvList[i].Key.SetKind(internalKeyKindDelete) 316 kvList[i].Value = []byte{} 317 } 318 require.NoError(t, wr.Set(*kvList[i].Key, kvList[i].Value)) 319 } 320 require.NoError(t, wr.FlushFinish()) 321 } 322 323 readData := func(pg *page) { 324 for i := 0; i < endIndex; i++ { 325 key := kvList[i].Key.UserKey 326 v, vexist, vcloser, kind := pg.get(key, hash.Crc32(key)) 327 pd := pg.bp.opts.KeyPrefixDeleteFunc(kvList[i].Key.UserKey) 328 if sortedkv.IsPrefixDeleteKey(pd) || i%3 == 0 { 329 if vexist { 330 t.Log(pd, i, kvList[i].Key.String()) 331 } 332 require.Equal(t, false, vexist) 333 } else { 334 require.Equal(t, kvList[i].Value, v) 335 require.Equal(t, internalKeyKindSet, kind) 336 vcloser() 337 } 338 } 339 } 340 341 bp, err := testOpenBitpage(true) 342 require.NoError(t, err) 343 pn, err1 := bp.NewPage() 344 require.NoError(t, err1) 345 writeData(bp, pn) 346 p := bp.GetPage(pn) 347 require.NoError(t, p.flush(nil, "")) 348 readData(p) 349 testCloseBitpage(t, bp) 350 351 for i := 0; i < num; i++ { 352 bp2, err2 := testOpenBitpage(true) 353 require.NoError(t, err2) 354 writeData(bp2, pn) 355 p2 := bp2.GetPage(pn) 356 require.NoError(t, p2.flush(nil, "")) 357 readData(p2) 358 testCloseBitpage(t, bp2) 359 } 360 }) 361 } 362 363 func TestBitpageCompact_PrefixDeleteKey2(t *testing.T) { 364 testcase(func(index int, params []bool) { 365 dir := testDir 366 defer os.RemoveAll(dir) 367 os.RemoveAll(dir) 368 369 var endIndex int 370 var pdVers []uint64 371 stepCount := 100 372 seqNum := uint64(1) 373 count := 2 * stepCount 374 kvList := sortedkv.MakeSlotSortedKVList2(0, count, seqNum, 10, testSlotId) 375 seqNum += uint64(count) 376 377 isPrefixDelete := func(v uint64) bool { 378 if len(pdVers) == 0 { 379 return false 380 } 381 for i := range pdVers { 382 if pdVers[i] == v { 383 return true 384 } 385 } 386 return false 387 } 388 389 writeData := func(bp *Bitpage, pn PageNum) { 390 wr := bp.GetPageWriter(pn, nil) 391 startIndex := endIndex 392 endIndex = startIndex + stepCount 393 for i := startIndex; i < endIndex; i++ { 394 require.NoError(t, wr.Set(*kvList[i].Key, kvList[i].Value)) 395 } 396 require.NoError(t, wr.FlushFinish()) 397 } 398 399 writePrefixDeleteKey := func(bp *Bitpage, pn PageNum, versions []uint64) { 400 if len(versions) == 0 { 401 return 402 } 403 wr := bp.GetPageWriter(pn, nil) 404 for _, version := range versions { 405 key := sortedkv.MakeKey2(nil, testSlotId, version) 406 seqNum++ 407 ikey := base.MakeInternalKey(key, seqNum, base.InternalKeyKindPrefixDelete) 408 require.NoError(t, wr.Set(ikey, []byte{})) 409 } 410 require.NoError(t, wr.FlushFinish()) 411 } 412 413 readData := func(pg *page) { 414 for i := 0; i < endIndex; i++ { 415 key := kvList[i].Key.UserKey 416 v, vexist, vcloser, kind := pg.get(key, hash.Crc32(key)) 417 pd := pg.bp.opts.KeyPrefixDeleteFunc(kvList[i].Key.UserKey) 418 if isPrefixDelete(pd) { 419 if vexist { 420 t.Log(pd, i, kvList[i].Key.String()) 421 } 422 require.Equal(t, false, vexist) 423 } else { 424 require.Equal(t, kvList[i].Value, v) 425 require.Equal(t, internalKeyKindSet, kind) 426 vcloser() 427 } 428 } 429 } 430 431 bp, err := testOpenBitpage(true) 432 require.NoError(t, err) 433 pn, err1 := bp.NewPage() 434 require.NoError(t, err1) 435 writeData(bp, pn) 436 p := bp.GetPage(pn) 437 require.NoError(t, p.flush(nil, "")) 438 readData(p) 439 440 pdVers = []uint64{101, 103, 105} 441 writePrefixDeleteKey(bp, pn, pdVers) 442 require.NoError(t, p.flush(nil, "")) 443 readData(p) 444 445 testCloseBitpage(t, bp) 446 }) 447 }