github.com/zuoyebang/bitalosdb@v1.1.1-0.20240516111551-79a8c4d8ce20/bithash/bithash_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 bithash 16 17 import ( 18 "bytes" 19 "encoding/binary" 20 "errors" 21 "fmt" 22 "io/fs" 23 "math/rand" 24 "os" 25 "runtime" 26 "strconv" 27 "sync" 28 "testing" 29 "time" 30 31 "github.com/stretchr/testify/require" 32 "github.com/zuoyebang/bitalosdb/internal/base" 33 "github.com/zuoyebang/bitalosdb/internal/compress" 34 "github.com/zuoyebang/bitalosdb/internal/hash" 35 "github.com/zuoyebang/bitalosdb/internal/list2" 36 "github.com/zuoyebang/bitalosdb/internal/options" 37 ) 38 39 const testdataDir = "test" 40 41 type testKvItem struct { 42 k []byte 43 v []byte 44 fn FileNum 45 } 46 47 func testGetBithashOpts(sz int) *options.BithashOptions { 48 opts := &options.BithashOptions{ 49 Options: &options.Options{ 50 FS: testFs, 51 Logger: base.DefaultLogger, 52 Compressor: compress.NoCompressor, 53 DeleteFilePacer: options.NewDefaultDeletionFileLimiter(), 54 BytesPerSync: 512 << 10, 55 }, 56 TableMaxSize: sz, 57 Index: 1, 58 } 59 return opts 60 } 61 62 func testBuildKV(num int) []testKvItem { 63 var kvList []testKvItem 64 for i := 0; i < num; i++ { 65 kvList = append(kvList, testKvItem{ 66 k: []byte("vip:uinfo:scancode:" + strconv.Itoa(i)), 67 v: testGenValue(2048)}) 68 } 69 70 return kvList 71 } 72 73 func testGenValue(size int) []byte { 74 buf := make([]byte, size) 75 for i := 0; i < size; i++ { 76 rand.Intn(122 - 65) 77 buf[i] = byte(rand.Intn(122-65) + 65) 78 } 79 return buf 80 } 81 82 func testOpenBithash() *Bithash { 83 opts := testGetBithashOpts(1 << 20) 84 _, err := os.Stat(testdataDir) 85 if nil != err && !os.IsExist(err) { 86 err = os.MkdirAll(testdataDir, 0775) 87 if nil != err { 88 panic(err) 89 } 90 } 91 bithash, err := Open(testdataDir, opts) 92 if err != nil { 93 panic(err) 94 } 95 96 return bithash 97 } 98 99 func testOpenBithash_64MB() *Bithash { 100 opts := testGetBithashOpts(64 << 20) 101 _, err := os.Stat(testdataDir) 102 if nil != err && !os.IsExist(err) { 103 err = os.MkdirAll(testdataDir, 0775) 104 if nil != err { 105 panic(err) 106 } 107 } 108 bithash, err := Open(testdataDir, opts) 109 if err != nil { 110 panic(err) 111 } 112 113 return bithash 114 } 115 116 func getSlotIndexBuf(key []byte) []byte { 117 index := hash.Fnv32(key) % 1024 118 buf := make([]byte, 4) 119 binary.BigEndian.PutUint32(buf, index) 120 return buf 121 } 122 123 func testBithashClose(t *testing.T, b *Bithash) { 124 require.NoError(t, b.Close()) 125 b.deleteFilePacer.Close() 126 } 127 128 func TestBithashOpen(t *testing.T) { 129 defer os.RemoveAll(testdataDir) 130 os.RemoveAll(testdataDir) 131 b := testOpenBithash() 132 require.Equal(t, 0, len(b.mufn.fnMap)) 133 key := []byte("key") 134 ek := make([]byte, len(key)+4) 135 pos := copy(ek, getSlotIndexBuf(key)) 136 copy(ek[pos:], key) 137 khash := hash.Crc32(ek) 138 _, _, err := b.Get(ek, khash, 5) 139 require.Equal(t, ErrBhFileNumZero, err) 140 testBithashClose(t, b) 141 } 142 143 func testGetGID() uint64 { 144 b := make([]byte, 64) 145 b = b[:runtime.Stack(b, false)] 146 b = bytes.TrimPrefix(b, []byte("goroutine ")) 147 b = b[:bytes.IndexByte(b, ' ')] 148 n, _ := strconv.ParseUint(string(b), 10, 64) 149 return n 150 } 151 152 func testBithashWriterFlush(b *Bithash) { 153 kvList := testBuildKV(10000) 154 fmt.Println("testBithashWriterFlush", testGetGID()) 155 bhWriter, err := b.FlushStart() 156 if err != nil { 157 panic(err) 158 } 159 for i, item := range kvList { 160 ik := base.MakeInternalKey(item.k, 0, InternalKeyKindSet) 161 kvList[i].fn, err = bhWriter.Add(ik, item.v) 162 if err != nil { 163 panic(err) 164 } 165 } 166 err = b.FlushFinish(bhWriter) 167 if err != nil { 168 panic(err) 169 } 170 } 171 172 func testBithashWriterFlushAndGet(b *Bithash) { 173 gid := testGetGID() 174 var kvList []testKvItem 175 for i := 0; i < 1000; i++ { 176 kvList = append(kvList, testKvItem{ 177 k: []byte(fmt.Sprintf("vip:uinfo:scancode:%d:%d", gid, i)), 178 v: testGenValue(2048)}, 179 ) 180 } 181 182 bhWriter, err := b.FlushStart() 183 if err != nil { 184 panic(err) 185 } 186 fmt.Println("testBithashWriterFlush write start", gid, bhWriter.GetFileNum()) 187 for i, item := range kvList { 188 ik := base.MakeInternalKey(item.k, 0, InternalKeyKindSet) 189 kvList[i].fn, err = bhWriter.Add(ik, item.v) 190 if err != nil { 191 panic(err) 192 } 193 } 194 err = b.FlushFinish(bhWriter) 195 if err != nil { 196 panic(err) 197 } 198 199 fmt.Println("testBithashWriterFlush write done", gid) 200 201 for _, item := range kvList { 202 khash := hash.Crc32(item.k) 203 value, putBytePool, err := b.Get(item.k, khash, item.fn) 204 if err != nil { 205 fmt.Println("get fail", gid, string(item.k), item.fn) 206 } 207 if !bytes.Equal(value, item.v) { 208 panic(fmt.Sprintf("check kv fail k=%s fm=%d", string(item.k), uint64(item.fn))) 209 } 210 putBytePool() 211 } 212 213 fmt.Println("testBithashWriterFlush finish", gid) 214 } 215 216 func TestBithashCompactAndGet(t *testing.T) { 217 defer os.RemoveAll(testdataDir) 218 os.RemoveAll(testdataDir) 219 seqNum := uint64(1) 220 b := testOpenBithash() 221 222 num := 2000 223 kvList := testBuildKV(num) 224 bhWriter, err := b.FlushStart() 225 require.NoError(t, err) 226 for i, item := range kvList { 227 ik := base.MakeInternalKey(item.k, seqNum, InternalKeyKindSet) 228 kvList[i].fn, err = bhWriter.Add(ik, item.v) 229 if err != nil { 230 panic(err) 231 } 232 seqNum++ 233 if i > 1000 { 234 break 235 } 236 } 237 require.NoError(t, b.FlushFinish(bhWriter)) 238 bhWriter, err = b.FlushStart() 239 require.NoError(t, err) 240 for i, item := range kvList { 241 ik := base.MakeInternalKey(item.k, seqNum, InternalKeyKindSet) 242 kvList[i].fn, err = bhWriter.Add(ik, item.v) 243 if err != nil { 244 panic(err) 245 } 246 seqNum++ 247 } 248 require.NoError(t, b.FlushFinish(bhWriter)) 249 testBithashClose(t, b) 250 251 b = testOpenBithash() 252 bw, err1 := b.NewBithashWriter(true) 253 require.NoError(t, err1) 254 255 newFileNum := bw.GetFileNum() 256 fileNums := make([]FileNum, 4) 257 fileNums[0] = FileNum(1) 258 fileNums[1] = FileNum(2) 259 fileNums[2] = FileNum(3) 260 fileNums[3] = FileNum(4) 261 262 compactFile := func(fileNum FileNum) error { 263 iter, err := b.NewTableIter(fileNum) 264 if err != nil { 265 return err 266 } 267 defer func() { 268 require.NoError(t, iter.Close()) 269 }() 270 i := 0 271 for k, v, fn := iter.First(); iter.Valid(); k, v, fn = iter.Next() { 272 if err = bw.AddIkey(k, v, hash.Crc32(k.UserKey), fn); err != nil { 273 return err 274 } 275 i++ 276 } 277 return nil 278 } 279 280 for _, fn := range fileNums { 281 err = compactFile(fn) 282 require.NoError(t, err) 283 b.SetFileNumMap(newFileNum, fn) 284 b.RemoveTableFiles([]FileNum{fn}) 285 } 286 287 require.NoError(t, bw.Finish()) 288 289 for _, item := range kvList { 290 khash := hash.Crc32(item.k) 291 value, putBytePool, err := b.Get(item.k, khash, item.fn) 292 require.NoError(t, err) 293 if !bytes.Equal(item.v, value) { 294 t.Fatalf("get fail key:%s exp:%d act:%d", string(item.k), len(item.v), len(value)) 295 } 296 putBytePool() 297 } 298 299 testBithashClose(t, b) 300 301 b = testOpenBithash() 302 iter, err := b.NewTableIter(newFileNum) 303 if err != nil { 304 t.Fatal(err) 305 } 306 for k, _, fn := iter.First(); iter.Valid(); k, _, fn = iter.Next() { 307 khash := hash.Crc32(k.UserKey) 308 v, pool, err := b.Get(k.UserKey, khash, fn) 309 require.NoError(t, err) 310 require.Equal(t, 2048, len(v)) 311 if pool != nil { 312 pool() 313 } 314 } 315 require.NoError(t, iter.Close()) 316 testBithashClose(t, b) 317 } 318 319 func TestBithashCompactInterrupt(t *testing.T) { 320 defer os.RemoveAll(testdataDir) 321 os.RemoveAll(testdataDir) 322 seqNum := uint64(1) 323 b := testOpenBithash() 324 325 num := 1200 326 kvList := testBuildKV(num) 327 bhWriter, err := b.FlushStart() 328 require.NoError(t, err) 329 for i, item := range kvList { 330 ik := base.MakeInternalKey(item.k, seqNum, InternalKeyKindSet) 331 kvList[i].fn, err = bhWriter.Add(ik, item.v) 332 if err != nil { 333 panic(err) 334 } 335 seqNum++ 336 } 337 require.NoError(t, b.FlushFinish(bhWriter)) 338 testBithashClose(t, b) 339 340 b = testOpenBithash() 341 bw, err := b.NewBithashWriter(true) 342 require.NoError(t, err) 343 newFileNum := bw.GetFileNum() 344 fmt.Println("newFileNum", newFileNum) 345 fileNums := make([]FileNum, 2) 346 fileNums[0] = FileNum(1) 347 fileNums[1] = FileNum(2) 348 compactFile := func(fileNum FileNum) error { 349 iter, e := b.NewTableIter(fileNum) 350 if e != nil { 351 return e 352 } 353 defer func() { 354 require.NoError(t, iter.Close()) 355 }() 356 i := 0 357 for k, v, fn := iter.First(); iter.Valid(); k, v, fn = iter.Next() { 358 if e = bw.AddIkey(k, v, hash.Crc32(k.UserKey), fn); e != nil { 359 return e 360 } 361 i++ 362 if i == 100 { 363 return nil 364 } 365 } 366 return nil 367 } 368 369 for _, fn := range fileNums { 370 err = compactFile(fn) 371 if err != nil { 372 t.Fatalf("compactFile fail fn:%d err:%s", fn, err) 373 } 374 } 375 376 b = testOpenBithash() 377 filename := MakeFilepath(b.fs, b.dirname, fileTypeTable, newFileNum) 378 _, err = b.fs.Stat(filename) 379 require.Equal(t, true, errors.Is(err, fs.ErrNotExist)) 380 _, ok := b.meta.mu.filesMeta[newFileNum] 381 require.Equal(t, false, ok) 382 testBithashClose(t, b) 383 } 384 385 func TestBithashWriterFlush(t *testing.T) { 386 defer os.RemoveAll(testdataDir) 387 os.RemoveAll(testdataDir) 388 b := testOpenBithash() 389 testBithashWriterFlush(b) 390 testBithashClose(t, b) 391 } 392 393 func TestBithashWriterConcurrencyFlush(t *testing.T) { 394 defer os.RemoveAll(testdataDir) 395 os.RemoveAll(testdataDir) 396 var wg sync.WaitGroup 397 b := testOpenBithash() 398 for i := 0; i < 1; i++ { 399 wg.Add(1) 400 go func() { 401 defer wg.Done() 402 testBithashWriterFlushAndGet(b) 403 }() 404 } 405 wg.Wait() 406 testBithashClose(t, b) 407 } 408 409 func TestBithashFlushAndGet(t *testing.T) { 410 defer os.RemoveAll(testdataDir) 411 os.RemoveAll(testdataDir) 412 b := testOpenBithash() 413 kvList := testBuildKV(5000) 414 bhWriter, err := b.FlushStart() 415 if err != nil { 416 panic(err) 417 } 418 for i, item := range kvList { 419 ik := base.MakeInternalKey(item.k, 0, InternalKeyKindSet) 420 kvList[i].fn, err = bhWriter.Add(ik, item.v) 421 if err != nil { 422 panic(err) 423 } 424 } 425 err = b.FlushFinish(bhWriter) 426 if err != nil { 427 panic(err) 428 } 429 430 for _, item := range kvList { 431 khash := hash.Crc32(item.k) 432 value, putBytePool, err := b.Get(item.k, khash, item.fn) 433 if err != nil { 434 panic(err) 435 } 436 if !bytes.Equal(value, item.v) { 437 panic(fmt.Sprintf("check kv fail k=%s fm=%d", string(item.k), uint64(item.fn))) 438 } 439 putBytePool() 440 } 441 442 testBithashClose(t, b) 443 } 444 445 func TestBithashFlushCloseAndGet(t *testing.T) { 446 defer os.RemoveAll(testdataDir) 447 os.RemoveAll(testdataDir) 448 kvList := testBuildKV(10000) 449 b := testOpenBithash() 450 bhWriter, err := b.FlushStart() 451 if err != nil { 452 panic(err) 453 } 454 for i, item := range kvList { 455 ik := base.MakeInternalKey(item.k, 0, InternalKeyKindSet) 456 kvList[i].fn, err = bhWriter.Add(ik, item.v) 457 if err != nil { 458 panic(err) 459 } 460 } 461 if err = b.FlushFinish(bhWriter); err != nil { 462 panic(err) 463 } 464 testBithashClose(t, b) 465 466 b1 := testOpenBithash() 467 for _, item := range kvList { 468 khash := hash.Crc32(item.k) 469 value, putBytePool, err := b1.Get(item.k, khash, item.fn) 470 if err != nil { 471 panic(err) 472 } 473 if !bytes.Equal(value, item.v) { 474 fmt.Println("check kv fail", string(item.k), item.fn) 475 } 476 putBytePool() 477 } 478 479 testBithashClose(t, b1) 480 } 481 482 func TestBithashWriteAndGet(t *testing.T) { 483 defer os.RemoveAll(testdataDir) 484 os.RemoveAll(testdataDir) 485 seqNum := uint64(1) 486 b := testOpenBithash() 487 num := 2000 488 489 fmt.Println("open1 b.mufn.fnMap", len(b.mufn.fnMap)) 490 for k, v := range b.mufn.fnMap { 491 fmt.Println("open1", k, v) 492 } 493 494 kvList := testBuildKV(num) 495 bhWriter, err := b.FlushStart() 496 require.NoError(t, err) 497 for i, item := range kvList { 498 ik := base.MakeInternalKey(item.k, seqNum, InternalKeyKindSet) 499 kvList[i].fn, err = bhWriter.Add(ik, item.v) 500 if err != nil { 501 panic(err) 502 } 503 seqNum++ 504 } 505 require.NoError(t, b.FlushFinish(bhWriter)) 506 507 fmt.Println("write1 kv finish") 508 509 for _, item := range kvList { 510 khash := hash.Crc32(item.k) 511 value, putBytePool, err := b.Get(item.k, khash, item.fn) 512 require.NoError(t, err) 513 if !bytes.Equal(item.v, value) { 514 t.Fatalf("key:%s\nexp:%s\nact:%s", string(item.k), string(item.v), string(value)) 515 } 516 putBytePool() 517 } 518 519 testBithashClose(t, b) 520 521 b = testOpenBithash() 522 fmt.Println("open2 b.mufn.fnMap", len(b.mufn.fnMap)) 523 for k, v := range b.mufn.fnMap { 524 fmt.Println("open2", k, v) 525 } 526 527 kvList = testBuildKV(num) 528 bhWriter, err = b.FlushStart() 529 require.NoError(t, err) 530 for i, item := range kvList { 531 ik := base.MakeInternalKey(item.k, seqNum, InternalKeyKindSet) 532 kvList[i].fn, err = bhWriter.Add(ik, item.v) 533 if err != nil { 534 panic(err) 535 } 536 seqNum++ 537 } 538 err = b.FlushFinish(bhWriter) 539 require.NoError(t, err) 540 541 fmt.Println("write2 kv finish") 542 543 fmt.Println("start get") 544 for _, item := range kvList { 545 khash := hash.Crc32(item.k) 546 value, putBytePool, err := b.Get(item.k, khash, item.fn) 547 require.NoError(t, err) 548 if !bytes.Equal(item.v, value) { 549 t.Fatalf("key:%s exp:%s act:%s", string(item.k), string(item.v), string(value)) 550 } 551 putBytePool() 552 } 553 554 testBithashClose(t, b) 555 556 b = testOpenBithash() 557 fmt.Println("open3 b.mufn.fnMap", len(b.mufn.fnMap)) 558 for k, v := range b.mufn.fnMap { 559 fmt.Println("open3", k, v) 560 } 561 562 testBithashClose(t, b) 563 } 564 565 func TestBithashWriteAndClose(t *testing.T) { 566 defer os.RemoveAll(testdataDir) 567 os.RemoveAll(testdataDir) 568 seqNum := uint64(1) 569 570 writeFunc := func() { 571 b := testOpenBithash() 572 num := 1900 573 kvList := testBuildKV(num) 574 bhWriter, err := b.FlushStart() 575 require.NoError(t, err) 576 for i, item := range kvList { 577 ik := base.MakeInternalKey(item.k, seqNum, InternalKeyKindSet) 578 kvList[i].fn, err = bhWriter.Add(ik, item.v) 579 if err != nil { 580 panic(err) 581 } 582 seqNum++ 583 } 584 require.NoError(t, b.FlushFinish(bhWriter)) 585 testBithashClose(t, b) 586 b = testOpenBithash() 587 for _, item := range kvList { 588 khash := hash.Crc32(item.k) 589 value, putBytePool, e := b.Get(item.k, khash, item.fn) 590 if e != nil { 591 t.Fatalf("get fail key:%s err:%s", string(item.k), err) 592 } 593 if !bytes.Equal(item.v, value) { 594 t.Fatalf("get fail key:%s exp:%d act:%d", string(item.k), len(item.v), len(value)) 595 } 596 putBytePool() 597 } 598 testBithashClose(t, b) 599 } 600 601 for i := 0; i < 10; i++ { 602 fmt.Println("openclose", i) 603 writeFunc() 604 } 605 } 606 607 func TestBithashKeyRepeat(t *testing.T) { 608 defer os.RemoveAll(testdataDir) 609 os.RemoveAll(testdataDir) 610 611 seqNum := uint64(1) 612 b := testOpenBithash() 613 num := 500 614 615 fmt.Println("start write 1") 616 617 kvList := testBuildKV(num) 618 bhWriter, err := b.FlushStart() 619 require.NoError(t, err) 620 for i, item := range kvList { 621 ik := base.MakeInternalKey(item.k, seqNum, InternalKeyKindSet) 622 kvList[i].fn, err = bhWriter.Add(ik, item.v) 623 if err != nil { 624 panic(err) 625 } 626 seqNum++ 627 } 628 err = b.FlushFinish(bhWriter) 629 require.NoError(t, err) 630 631 fmt.Println("start write 2") 632 633 kvList = testBuildKV(num) 634 bhWriter, err = b.FlushStart() 635 require.NoError(t, err) 636 for i, item := range kvList { 637 ik := base.MakeInternalKey(item.k, seqNum, InternalKeyKindSet) 638 kvList[i].fn, err = bhWriter.Add(ik, item.v) 639 if err != nil { 640 panic(err) 641 } 642 seqNum++ 643 } 644 err = b.FlushFinish(bhWriter) 645 require.NoError(t, err) 646 647 fmt.Println("start get") 648 649 for _, item := range kvList { 650 khash := hash.Crc32(item.k) 651 value, putBytePool, err := b.Get(item.k, khash, item.fn) 652 require.NoError(t, err) 653 require.Equal(t, item.v, value) 654 putBytePool() 655 } 656 657 testBithashClose(t, b) 658 } 659 660 func TestBithashKeyHashConflict(t *testing.T) { 661 defer os.RemoveAll(testdataDir) 662 os.RemoveAll(testdataDir) 663 664 seqNum := uint64(1) 665 b := testOpenBithash_64MB() 666 667 conflictKeys := []string{ 668 "m_T`UpDSxCr`ySymsoev", 669 "yjdJKx\\xjRgcMn\\OHr`_", 670 "tNurPFGNoJ_UROdugxXM", 671 "`pheCoLCfcAr_qCdaIhE", 672 "NvxogGOdNnpRAnRAVaW]", 673 "qAGjXZSJkJpFbojaeFFu", 674 "t_paOJENejFVUfP]npTQ", 675 "WwfjcpTd\\tRZ\\WgYVUZK", 676 "wQtERVmd^xpSk_]n[_\\k", 677 "Wd\\[BIVamMWtMyPEybOa", 678 "\\sJNnWFpmpjEumBPT]ol", 679 "yfNJhKZyKikCokteoMag", 680 } 681 682 var conflictKvList []testKvItem 683 for _, k := range conflictKeys { 684 conflictKvList = append(conflictKvList, testKvItem{ 685 k: []byte(k), 686 v: testGenValue(2048), 687 }) 688 } 689 690 fmt.Println("start write 1") 691 692 kvList := testBuildKV(100) 693 bhWriter, err := b.FlushStart() 694 require.NoError(t, err) 695 for i, item := range kvList { 696 ik := base.MakeInternalKey(item.k, seqNum, InternalKeyKindSet) 697 kvList[i].fn, err = bhWriter.Add(ik, item.v) 698 if err != nil { 699 panic(err) 700 } 701 seqNum++ 702 if i == 50 { 703 for i, item := range conflictKvList { 704 ik := base.MakeInternalKey(item.k, seqNum, InternalKeyKindSet) 705 conflictKvList[i].fn, err = bhWriter.Add(ik, item.v) 706 if err != nil { 707 panic(err) 708 } 709 seqNum++ 710 } 711 } 712 } 713 714 err = b.FlushFinish(bhWriter) 715 require.NoError(t, err) 716 717 readKv := func() { 718 for _, item := range kvList { 719 value, putBytePool, err := b.Get(item.k, hash.Crc32(item.k), item.fn) 720 require.NoError(t, err) 721 require.Equal(t, item.v, value) 722 putBytePool() 723 } 724 for _, item := range conflictKvList { 725 value, putBytePool, err := b.Get(item.k, hash.Crc32(item.k), item.fn) 726 require.NoError(t, err) 727 require.Equal(t, item.v, value) 728 putBytePool() 729 } 730 } 731 732 fmt.Println("start get1") 733 readKv() 734 735 bhWriter, err = b.FlushStart() 736 require.NoError(t, err) 737 bhWriter.compact = true 738 err = b.FlushFinish(bhWriter) 739 require.NoError(t, err) 740 741 fmt.Println("start get2") 742 readKv() 743 744 fm := b.meta.mu.filesMeta[FileNum(1)] 745 fmt.Println("debuginfo", b.DebugInfo("test")) 746 fmt.Println("fm", fm) 747 require.Equal(t, uint32(112), fm.keyNum) 748 require.Equal(t, uint32(12), fm.conflictKeyNum) 749 testBithashClose(t, b) 750 } 751 752 func TestBithashOpenTableErrRebuild(t *testing.T) { 753 defer os.RemoveAll(testdataDir) 754 os.RemoveAll(testdataDir) 755 756 b := testOpenBithash() 757 seqNum := uint64(1) 758 num := 1200 759 kvList := testBuildKV(num) 760 bhWriter, err := b.FlushStart() 761 require.NoError(t, err) 762 for i, item := range kvList { 763 ik := base.MakeInternalKey(item.k, seqNum, InternalKeyKindSet) 764 kvList[i].fn, err = bhWriter.Add(ik, item.v) 765 require.NoError(t, err) 766 seqNum++ 767 } 768 require.NoError(t, b.FlushFinish(bhWriter)) 769 n, err1 := bhWriter.wr.writer.Write([]byte("panic")) 770 require.NoError(t, err1) 771 require.Equal(t, 5, n) 772 require.NoError(t, bhWriter.wr.Flush()) 773 //if bhWriter.wr.currentOffset != uint32(409836) { 774 // t.Fatalf("check currentOffset exp:409836 act:%d", bhWriter.wr.currentOffset) 775 //} 776 require.Equal(t, uint32(409836), bhWriter.wr.currentOffset) 777 require.Equal(t, int64(409841), bhWriter.wr.fileStatSize()) 778 time.Sleep(2 * time.Second) 779 testBithashClose(t, b) 780 781 b = testOpenBithash() 782 bhWriter, err = b.FlushStart() 783 require.NoError(t, err) 784 require.Equal(t, uint32(409836), bhWriter.wr.currentOffset) 785 require.Equal(t, int64(409841), bhWriter.wr.fileStatSize()) 786 require.NoError(t, b.FlushFinish(bhWriter)) 787 time.Sleep(2 * time.Second) 788 for _, item := range kvList { 789 khash := hash.Crc32(item.k) 790 value, putBytePool, err2 := b.Get(item.k, khash, item.fn) 791 require.NoError(t, err2) 792 require.Equal(t, item.v, value) 793 putBytePool() 794 } 795 testBithashClose(t, b) 796 } 797 798 func TestBithashMemSize(t *testing.T) { 799 defer os.RemoveAll(testdataDir) 800 os.RemoveAll(testdataDir) 801 b := testOpenBithash_64MB() 802 803 value := []byte("v") 804 805 bhWriter, err := b.FlushStart() 806 require.NoError(t, err) 807 808 lastFn := FileNum(0) 809 fileNum := make([]int, 200) 810 totalNum := 20 << 20 811 812 bt := time.Now() 813 for i := 0; i < totalNum; i++ { 814 key := []byte(fmt.Sprintf("bit_%d+hash_test%d+%d", i, i+512, i+1024)) 815 ik := base.MakeInternalKey(key, uint64(i), InternalKeyKindSet) 816 fn, err := bhWriter.Add(ik, value) 817 if err != nil { 818 panic(err) 819 } 820 821 if fn != lastFn { 822 fileNum[int(fn)] = i 823 lastFn = fn 824 } 825 } 826 require.NoError(t, b.FlushFinish(bhWriter)) 827 et := time.Since(bt) 828 fmt.Printf("build index time cost = %v\n", et) 829 830 bt = time.Now() 831 for i := 0; i < totalNum; i++ { 832 key := []byte(fmt.Sprintf("bit_%d+hash_test%d+%d", i, i+512, i+1024)) 833 for j := 1; j < len(fileNum); j++ { 834 if i >= fileNum[j] && i < fileNum[j+1] || i >= fileNum[j] && fileNum[j+1] == 0 { 835 khash := hash.Crc32(key) 836 v, putBytePool, err := b.Get(key, khash, FileNum(j)) 837 if err != nil { 838 fmt.Printf("check kv fail k=%s fn=%d\n", key, j) 839 break 840 } 841 if !bytes.Equal(value, v) { 842 panic(fmt.Sprintf("check kv fail k=%s fn=%d\n", key, j)) 843 } 844 putBytePool() 845 break 846 } 847 } 848 } 849 et = time.Since(bt) 850 fmt.Printf("scan index time cost = %v\n", et) 851 852 printMemStats() 853 } 854 855 const MB = 1024 * 1024 856 857 func printMemStats() { 858 var m runtime.MemStats 859 runtime.ReadMemStats(&m) 860 fmt.Printf("Map MEM: Alloc=%vMB; TotalAlloc=%vMB; SYS=%vMB; Mallocs=%v; Frees=%v; HeapAlloc=%vMB; HeapSys=%vMB; HeapIdle=%vMB; HeapReleased=%vMB; GCSys=%vMB; NextGC=%vMB; NumGC=%v; NumForcedGC=%v\n", 861 m.Alloc/MB, m.TotalAlloc/MB, m.Sys/MB, m.Mallocs, m.Frees, m.HeapAlloc/MB, m.HeapSys/MB, m.HeapIdle/MB, m.HeapReleased/MB, 862 m.GCSys/MB, m.NextGC/MB, m.NumGC, m.NumForcedGC) 863 } 864 865 func TestInitManifest(t *testing.T) { 866 defer os.RemoveAll(testdataDir) 867 os.RemoveAll(testdataDir) 868 bithash := testOpenBithash() 869 defer func() { 870 require.NoError(t, bithash.Close()) 871 }() 872 873 require.Equal(t, versionV1, bithash.meta.version) 874 875 for fileNum, pos := range bithash.meta.mu.filesPos { 876 fmt.Println("fileMeta scan: ", fileNum, pos) 877 fileMeta := bithash.meta.getFileMetadata(fileNum) 878 fmt.Println("fileMeta value: ", fileMeta) 879 } 880 } 881 882 func TestBithashStats(t *testing.T) { 883 defer os.RemoveAll(testdataDir) 884 os.RemoveAll(testdataDir) 885 seqNum := uint64(1) 886 b := testOpenBithash() 887 defer testBithashClose(t, b) 888 889 num := 2000 890 kvList := testBuildKV(num) 891 892 writeFunc := func() { 893 bhWriter, err := b.FlushStart() 894 require.NoError(t, err) 895 for i, item := range kvList { 896 ik := base.MakeInternalKey(item.k, seqNum, InternalKeyKindSet) 897 kvList[i].fn, err = bhWriter.Add(ik, item.v) 898 if err != nil { 899 panic(err) 900 } 901 seqNum++ 902 } 903 err = b.FlushFinish(bhWriter) 904 require.NoError(t, err) 905 } 906 907 deleteFunc := func() { 908 for i, item := range kvList { 909 if i%2 == 0 { 910 b.Delete(item.fn) 911 } 912 } 913 } 914 915 writeFunc() 916 deleteFunc() 917 918 require.Equal(t, uint64(2000), b.stats.KeyTotal.Load()) 919 require.Equal(t, uint64(1000), b.stats.DelKeyTotal.Load()) 920 } 921 922 func TestBithashReadFile(t *testing.T) { 923 fn := FileNum(1) 924 dir := "" 925 if dir == "" { 926 return 927 } 928 929 opts := &options.BithashOptions{ 930 Options: &options.Options{ 931 FS: testFs, 932 Logger: base.DefaultLogger, 933 Compressor: compress.SnappyCompressor, 934 }, 935 TableMaxSize: 512 << 20, 936 Index: 1, 937 } 938 939 b := &Bithash{ 940 dirname: dir, 941 fs: opts.FS, 942 tableMaxSize: opts.TableMaxSize, 943 logger: opts.Logger, 944 compressor: opts.Compressor, 945 index: opts.Index, 946 bhtReaders: sync.Map{}, 947 rwwWriters: sync.Map{}, 948 stats: &Stats{}, 949 } 950 b.mufn.fnMap = make(map[FileNum]FileNum, 1<<10) 951 b.mutw.mutableWriters = list2.NewStack() 952 953 defer func() { 954 if err := b.Close(); err != nil { 955 t.Fatal(err) 956 } 957 }() 958 959 filename := MakeFilepath(b.fs, b.dirname, fileTypeTable, fn) 960 fmt.Println("filename", filename) 961 962 f, err := b.fs.Open(filename) 963 if err != nil { 964 t.Fatal(err) 965 } 966 967 r, err := NewReader(b, f, FileReopenOpt{fs: b.fs, filename: filename, fileNum: fn, readOnly: true}) 968 if err != nil { 969 t.Fatal(err) 970 } 971 972 b.addReaders(r) 973 b.mufn.fnMap[fn] = fn 974 975 fmt.Println("dataBH", r.dataBH) 976 fmt.Println("indexHashBH", r.indexHashBH) 977 fmt.Println("conflictBH", r.conflictBH) 978 fmt.Println("conflictBuf len", len(r.conflictBuf)) 979 fmt.Println("indexHash", r.indexHash.Size(), r.indexHash.Length()) 980 }