| 633 | } |
| 634 | |
| 635 | void TmpFileMgrTest::TestScratchRangeRecycling(bool punch_holes) { |
| 636 | vector<string> tmp_dirs({"/tmp/tmp-file-mgr-test.1", "/tmp/tmp-file-mgr-test.2"}); |
| 637 | RemoveAndCreateDirs(tmp_dirs); |
| 638 | TmpFileMgr tmp_file_mgr; |
| 639 | ASSERT_OK(tmp_file_mgr.InitCustom(tmp_dirs, false, "", punch_holes, metrics_.get())); |
| 640 | TUniqueId id; |
| 641 | |
| 642 | TmpFileGroup file_group(&tmp_file_mgr, io_mgr(), profile_, id); |
| 643 | int64_t expected_scratch_bytes_allocated = 0; |
| 644 | // The max value of expected_scratch_bytes_allocated throughout this test. |
| 645 | int64_t max_scratch_bytes_allocated = 0; |
| 646 | // Test some different allocation sizes. |
| 647 | checkHWMMetrics(0, 0); |
| 648 | // Hole punching only reclaims space in 4kb block sizes. |
| 649 | int min_alloc_size = punch_holes ? TmpFileMgr::HOLE_PUNCH_BLOCK_SIZE_BYTES : 64; |
| 650 | for (int alloc_size = min_alloc_size; alloc_size <= 64 * 1024; alloc_size *= 2) { |
| 651 | // Generate some data. |
| 652 | const int BLOCKS = 5; |
| 653 | vector<vector<uint8_t>> data(BLOCKS); |
| 654 | for (int i = 0; i < BLOCKS; ++i) { |
| 655 | data[i].resize(alloc_size); |
| 656 | std::iota(data[i].begin(), data[i].end(), i); |
| 657 | } |
| 658 | |
| 659 | WriteRange::WriteDoneCallback callback = |
| 660 | bind(mem_fn(&TmpFileMgrTest::SignalCallback), this, _1); |
| 661 | vector<unique_ptr<TmpWriteHandle>> handles(BLOCKS); |
| 662 | // 'file_group' should allocate extra scratch bytes for this 'alloc_size'. |
| 663 | expected_scratch_bytes_allocated += alloc_size * BLOCKS; |
| 664 | const int TEST_ITERS = 5; |
| 665 | |
| 666 | // Make sure free space doesn't grow over several iterations. |
| 667 | for (int i = 0; i < TEST_ITERS; ++i) { |
| 668 | cb_counter_ = 0; |
| 669 | for (int j = 0; j < BLOCKS; ++j) { |
| 670 | ASSERT_OK(file_group.Write( |
| 671 | MemRange(data[j].data(), alloc_size), callback, &handles[j])); |
| 672 | } |
| 673 | WaitForCallbacks(BLOCKS); |
| 674 | EXPECT_EQ(expected_scratch_bytes_allocated, BytesAllocated(&file_group)); |
| 675 | checkHWMMetrics(expected_scratch_bytes_allocated, expected_scratch_bytes_allocated); |
| 676 | |
| 677 | // Read back and validate. |
| 678 | for (int j = 0; j < BLOCKS; ++j) { |
| 679 | vector<uint8_t> tmp(alloc_size); |
| 680 | ASSERT_OK(file_group.Read(handles[j].get(), MemRange(tmp.data(), alloc_size))); |
| 681 | EXPECT_EQ(0, memcmp(tmp.data(), data[j].data(), alloc_size)); |
| 682 | file_group.DestroyWriteHandle(move(handles[j])); |
| 683 | } |
| 684 | // With hole punching, the scratch space is not in use. Without hole punching it |
| 685 | // is in used, but will be reused by the next iteration. |
| 686 | int64_t expected_bytes_allocated = |
| 687 | punch_holes ? 0 : expected_scratch_bytes_allocated; |
| 688 | EXPECT_EQ(expected_bytes_allocated, BytesAllocated(&file_group)); |
| 689 | checkHWMMetrics(expected_bytes_allocated, expected_scratch_bytes_allocated); |
| 690 | } |
| 691 | /// No scratch should be in use for the next iteration if holes were punched. |
| 692 | max_scratch_bytes_allocated = |
nothing calls this directly
no test coverage detected