diff options
| author | Dan Engelbrecht <[email protected]> | 2024-10-03 16:42:57 +0200 |
|---|---|---|
| committer | GitHub Enterprise <[email protected]> | 2024-10-03 16:42:57 +0200 |
| commit | b13b5f48bb497aaf9f9f3d74aceb6e474cf12898 (patch) | |
| tree | 24b1ed63ece11fb773a0ecf41ce6308969468198 /src/zenstore/blockstore.cpp | |
| parent | 5.5.9-pre0 (diff) | |
| download | zen-b13b5f48bb497aaf9f9f3d74aceb6e474cf12898.tar.xz zen-b13b5f48bb497aaf9f9f3d74aceb6e474cf12898.zip | |
remove gc v1 (#121)
* kill gc v1
* block use of gc v1 from zen command line
* warn and flip to gcv2 if --gc-v2=false is specified for zenserver
Diffstat (limited to 'src/zenstore/blockstore.cpp')
| -rw-r--r-- | src/zenstore/blockstore.cpp | 648 |
1 files changed, 17 insertions, 631 deletions
diff --git a/src/zenstore/blockstore.cpp b/src/zenstore/blockstore.cpp index 2ae51d627..239b9e56b 100644 --- a/src/zenstore/blockstore.cpp +++ b/src/zenstore/blockstore.cpp @@ -659,26 +659,6 @@ BlockStore::WriteChunks(std::span<IoBuffer> Datas, uint32_t Alignment, const Wri } } -BlockStore::ReclaimSnapshotState -BlockStore::GetReclaimSnapshotState() -{ - ReclaimSnapshotState State; - RwLock::SharedLockScope _(m_InsertLock); - for (uint32_t BlockIndex : m_ActiveWriteBlocks) - { - State.m_ActiveWriteBlocks.insert(BlockIndex); - } - if (m_WriteBlock) - { - State.m_ActiveWriteBlocks.insert(m_WriteBlockIndex); - } - for (auto It : m_ChunkBlocks) - { - State.m_BlockIndexes.insert(It.first); - } - return State; -} - IoBuffer BlockStore::TryGetChunk(const BlockStoreLocation& Location) const { @@ -724,429 +704,6 @@ BlockStore::Flush(bool ForceNewBlock) } } -void -BlockStore::ReclaimSpace(const ReclaimSnapshotState& Snapshot, - const std::vector<BlockStoreLocation>& ChunkLocations, - const ChunkIndexArray& KeepChunkIndexes, - uint32_t PayloadAlignment, - bool DryRun, - const ReclaimCallback& ChangeCallback, - const ClaimDiskReserveCallback& DiskReserveCallback) -{ - ZEN_TRACE_CPU("BlockStore::ReclaimSpace"); - - uint64_t WriteBlockTimeUs = 0; - uint64_t WriteBlockLongestTimeUs = 0; - uint64_t ReadBlockTimeUs = 0; - uint64_t ReadBlockLongestTimeUs = 0; - uint64_t TotalChunkCount = ChunkLocations.size(); - uint64_t DeletedSize = 0; - uint64_t OldTotalSize = 0; - uint64_t NewTotalSize = 0; - - uint64_t MovedCount = 0; - uint64_t DeletedCount = 0; - - Stopwatch TotalTimer; - const auto _ = MakeGuard([&] { - ZEN_DEBUG( - "reclaim space for '{}' DONE after {}, write lock: {} ({}), read lock: {} ({}), collected {} bytes, deleted {} and moved " - "{} " - "of {} " - "chunks ({}).", - m_BlocksBasePath, - NiceTimeSpanMs(TotalTimer.GetElapsedTimeMs()), - NiceLatencyNs(WriteBlockTimeUs), - NiceLatencyNs(WriteBlockLongestTimeUs), - NiceLatencyNs(ReadBlockTimeUs), - NiceLatencyNs(ReadBlockLongestTimeUs), - NiceBytes(DeletedSize), - DeletedCount, - MovedCount, - TotalChunkCount, - NiceBytes(OldTotalSize)); - }); - - size_t BlockCount = Snapshot.m_BlockIndexes.size(); - if (BlockCount == 0) - { - ZEN_DEBUG("garbage collect for '{}' SKIPPED, no blocks to process", m_BlocksBasePath); - return; - } - - tsl::robin_set<size_t> KeepChunkMap; - KeepChunkMap.reserve(KeepChunkIndexes.size()); - for (size_t KeepChunkIndex : KeepChunkIndexes) - { - KeepChunkMap.insert(KeepChunkIndex); - } - - tsl::robin_map<uint32_t, size_t> BlockIndexToChunkMapIndex; - std::vector<ChunkIndexArray> BlockKeepChunks; - std::vector<ChunkIndexArray> BlockDeleteChunks; - - BlockIndexToChunkMapIndex.reserve(BlockCount); - BlockKeepChunks.reserve(BlockCount); - BlockDeleteChunks.reserve(BlockCount); - size_t GuesstimateCountPerBlock = TotalChunkCount / BlockCount / 2; - - size_t DeleteCount = 0; - for (size_t Index = 0; Index < TotalChunkCount; ++Index) - { - const BlockStoreLocation& Location = ChunkLocations[Index]; - if (!Snapshot.m_BlockIndexes.contains(Location.BlockIndex)) - { - // We did not know about the block when we took the snapshot, don't touch it - continue; - } - OldTotalSize += Location.Size; - auto BlockIndexPtr = BlockIndexToChunkMapIndex.find(Location.BlockIndex); - size_t ChunkMapIndex = 0; - if (BlockIndexPtr == BlockIndexToChunkMapIndex.end()) - { - ChunkMapIndex = BlockKeepChunks.size(); - BlockIndexToChunkMapIndex[Location.BlockIndex] = ChunkMapIndex; - BlockKeepChunks.resize(ChunkMapIndex + 1); - BlockKeepChunks.back().reserve(GuesstimateCountPerBlock); - BlockDeleteChunks.resize(ChunkMapIndex + 1); - BlockDeleteChunks.back().reserve(GuesstimateCountPerBlock); - } - else - { - ChunkMapIndex = BlockIndexPtr->second; - } - - if (KeepChunkMap.contains(Index)) - { - ChunkIndexArray& IndexMap = BlockKeepChunks[ChunkMapIndex]; - IndexMap.push_back(Index); - NewTotalSize += Location.Size; - continue; - } - ChunkIndexArray& IndexMap = BlockDeleteChunks[ChunkMapIndex]; - IndexMap.push_back(Index); - DeleteCount++; - } - - std::vector<uint32_t> BlocksToReWrite; - BlocksToReWrite.reserve(BlockIndexToChunkMapIndex.size()); - for (const auto& Entry : BlockIndexToChunkMapIndex) - { - uint32_t BlockIndex = Entry.first; - size_t ChunkMapIndex = Entry.second; - const ChunkIndexArray& ChunkMap = BlockDeleteChunks[ChunkMapIndex]; - if (ChunkMap.empty()) - { - continue; - } - BlocksToReWrite.push_back(BlockIndex); - } - - { - // Any known block not referenced should be added as well - RwLock::SharedLockScope __(m_InsertLock); - for (std::uint32_t BlockIndex : Snapshot.m_BlockIndexes) - { - if (!m_ChunkBlocks.contains(BlockIndex)) - { - continue; - } - bool WasActiveWriteBlock = Snapshot.m_ActiveWriteBlocks.contains(BlockIndex); - if (WasActiveWriteBlock) - { - continue; - } - if (BlockIndexToChunkMapIndex.contains(BlockIndex)) - { - continue; - } - size_t ChunkMapIndex = ChunkMapIndex = BlockKeepChunks.size(); - BlockIndexToChunkMapIndex[BlockIndex] = ChunkMapIndex; - BlockKeepChunks.resize(ChunkMapIndex + 1); - BlockDeleteChunks.resize(ChunkMapIndex + 1); - BlocksToReWrite.push_back(BlockIndex); - } - } - - if (DryRun) - { - ZEN_DEBUG("garbage collect for '{}' DISABLED, found {} {} chunks of total {} {}", - m_BlocksBasePath, - DeleteCount, - NiceBytes(OldTotalSize - NewTotalSize), - TotalChunkCount, - OldTotalSize); - return; - } - - try - { - ZEN_TRACE_CPU("BlockStore::ReclaimSpace::Compact"); - Ref<BlockStoreFile> NewBlockFile; - auto NewBlockFileGuard = MakeGuard([&]() { - if (NewBlockFile && NewBlockFile->IsOpen()) - { - ZEN_DEBUG("dropping incomplete cas block store file '{}'", NewBlockFile->GetPath()); - m_TotalSize.fetch_sub(NewBlockFile->FileSize(), std::memory_order::relaxed); - ZEN_ASSERT_SLOW(NewBlockFile->MetaSize() == 0); - NewBlockFile->MarkAsDeleteOnClose(); - } - }); - - uint64_t WriteOffset = 0; - uint32_t NewBlockIndex = 0; - for (uint32_t BlockIndex : BlocksToReWrite) - { - bool IsActiveWriteBlock = Snapshot.m_ActiveWriteBlocks.contains(BlockIndex); - - const size_t ChunkMapIndex = BlockIndexToChunkMapIndex[BlockIndex]; - - Ref<BlockStoreFile> OldBlockFile; - if (!IsActiveWriteBlock) - { - RwLock::SharedLockScope _i(m_InsertLock); - Stopwatch Timer; - const auto __ = MakeGuard([&] { - uint64_t ElapsedUs = Timer.GetElapsedTimeUs(); - WriteBlockTimeUs += ElapsedUs; - WriteBlockLongestTimeUs = std::max(ElapsedUs, WriteBlockLongestTimeUs); - }); - if (auto It = m_ChunkBlocks.find(BlockIndex); It != m_ChunkBlocks.end()) - { - OldBlockFile = It->second; - } - } - - ChunkIndexArray& KeepMap = BlockKeepChunks[ChunkMapIndex]; - if (KeepMap.empty()) - { - ZEN_TRACE_CPU("BlockStore::ReclaimSpace::DeleteBlock"); - - const ChunkIndexArray& DeleteMap = BlockDeleteChunks[ChunkMapIndex]; - for (size_t DeleteIndex : DeleteMap) - { - DeletedSize += ChunkLocations[DeleteIndex].Size; - } - ChangeCallback({}, DeleteMap); - DeletedCount += DeleteMap.size(); - if (OldBlockFile) - { - RwLock::ExclusiveLockScope _i(m_InsertLock); - Stopwatch Timer; - const auto __ = MakeGuard([&] { - uint64_t ElapsedUs = Timer.GetElapsedTimeUs(); - ReadBlockTimeUs += ElapsedUs; - ReadBlockLongestTimeUs = std::max(ElapsedUs, ReadBlockLongestTimeUs); - }); - ZEN_DEBUG("marking cas block store file '{}' for delete, block #{}", OldBlockFile->GetPath(), BlockIndex); - ZEN_ASSERT(m_ChunkBlocks[BlockIndex] == OldBlockFile); - m_ChunkBlocks.erase(BlockIndex); - m_TotalSize.fetch_sub(OldBlockFile->TotalSize(), std::memory_order::relaxed); - OldBlockFile->MarkAsDeleteOnClose(); - } - continue; - } - else if (!OldBlockFile && !IsActiveWriteBlock) - { - // If the block file pointed to does not exist, move any keep chunk them to deleted list - ZEN_ERROR("Expected to find block {} in {} - this should never happen, marking {} entries as deleted.", - BlockIndex, - m_BlocksBasePath, - KeepMap.size()); - - BlockDeleteChunks[ChunkMapIndex].insert(BlockDeleteChunks[ChunkMapIndex].end(), KeepMap.begin(), KeepMap.end()); - KeepMap.clear(); - } - else if (OldBlockFile && (OldBlockFile->FileSize() == 0)) - { - // Block created to accommodate missing blocks - ZEN_WARN("Missing block {} in {} - backing data for locations is missing, marking {} entries as deleted.", - BlockIndex, - m_BlocksBasePath, - KeepMap.size()); - - BlockDeleteChunks[ChunkMapIndex].insert(BlockDeleteChunks[ChunkMapIndex].end(), KeepMap.begin(), KeepMap.end()); - KeepMap.clear(); - } - - MovedChunksArray MovedChunks; - if (OldBlockFile) - { - ZEN_TRACE_CPU("BlockStore::ReclaimSpace::MoveBlock"); - - ZEN_INFO("Moving {} chunks from '{}' to new block", KeepMap.size(), GetBlockPath(m_BlocksBasePath, BlockIndex)); - - uint64_t OldBlockSize = OldBlockFile->FileSize(); - std::vector<uint8_t> Chunk; - for (const size_t& ChunkIndex : KeepMap) - { - const BlockStoreLocation ChunkLocation = ChunkLocations[ChunkIndex]; - if (ChunkLocation.Offset + ChunkLocation.Size > OldBlockSize) - { - ZEN_WARN( - "ReclaimSpace skipping chunk outside of block range in '{}', Chunk start {}, Chunk size {} in Block {}, Block " - "size {}", - m_BlocksBasePath, - ChunkLocation.Offset, - ChunkLocation.Size, - OldBlockFile->GetPath(), - OldBlockSize); - continue; - } - Chunk.resize(ChunkLocation.Size); - OldBlockFile->Read(Chunk.data(), ChunkLocation.Size, ChunkLocation.Offset); - - if (!NewBlockFile || (WriteOffset + ChunkLocation.Size > m_MaxBlockSize)) - { - uint32_t NextBlockIndex = m_WriteBlockIndex.load(std::memory_order_relaxed); - - if (NewBlockFile) - { - ZEN_ASSERT_SLOW(NewBlockFile->IsOpen()); - NewBlockFile->Flush(); - NewBlockFile = nullptr; - } - { - ChangeCallback(MovedChunks, {}); - MovedCount += KeepMap.size(); - MovedChunks.clear(); - RwLock::ExclusiveLockScope InsertLock(m_InsertLock); - Stopwatch Timer; - const auto ___ = MakeGuard([&] { - uint64_t ElapsedUs = Timer.GetElapsedTimeUs(); - ReadBlockTimeUs += ElapsedUs; - ReadBlockLongestTimeUs = std::max(ElapsedUs, ReadBlockLongestTimeUs); - }); - - std::filesystem::path NewBlockPath; - NextBlockIndex = GetFreeBlockIndex(NextBlockIndex, InsertLock, NewBlockPath); - if (NextBlockIndex == (uint32_t)m_MaxBlockCount) - { - ZEN_ERROR("unable to allocate a new block in '{}', count limit {} exeeded", - m_BlocksBasePath, - static_cast<uint64_t>(std::numeric_limits<uint32_t>::max()) + 1); - return; - } - - NewBlockFile = new BlockStoreFile(NewBlockPath); - m_ChunkBlocks[NextBlockIndex] = NewBlockFile; - } - - std::error_code Error; - DiskSpace Space = DiskSpaceInfo(m_BlocksBasePath, Error); - if (Error) - { - ZEN_ERROR("get disk space in '{}' FAILED, reason: '{}'", m_BlocksBasePath, Error.message()); - return; - } - if (Space.Free < m_MaxBlockSize) - { - uint64_t ReclaimedSpace = DiskReserveCallback(); - if (Space.Free + ReclaimedSpace < m_MaxBlockSize) - { - ZEN_WARN("garbage collect for '{}' FAILED, required disk space {}, free {}", - m_BlocksBasePath, - m_MaxBlockSize, - NiceBytes(Space.Free + ReclaimedSpace)); - RwLock::ExclusiveLockScope _l(m_InsertLock); - Stopwatch Timer; - const auto __ = MakeGuard([&] { - uint64_t ElapsedUs = Timer.GetElapsedTimeUs(); - ReadBlockTimeUs += ElapsedUs; - ReadBlockLongestTimeUs = std::max(ElapsedUs, ReadBlockLongestTimeUs); - }); - ZEN_ASSERT(m_ChunkBlocks[NextBlockIndex] == NewBlockFile); - ZEN_ASSERT_SLOW(!NewBlockFile->IsOpen()); - m_ChunkBlocks.erase(NextBlockIndex); - return; - } - - ZEN_INFO("using gc reserve for '{}', reclaimed {}, disk free {}", - m_BlocksBasePath, - ReclaimedSpace, - NiceBytes(Space.Free + ReclaimedSpace)); - } - NewBlockFile->Create(m_MaxBlockSize); - NewBlockIndex = NextBlockIndex; - WriteOffset = 0; - } - - NewBlockFile->Write(Chunk.data(), ChunkLocation.Size, WriteOffset); - MovedChunks.push_back( - {ChunkIndex, - {.BlockIndex = NewBlockIndex, .Offset = gsl::narrow<uint32_t>(WriteOffset), .Size = ChunkLocation.Size}}); - uint64_t OldOffset = WriteOffset; - WriteOffset = RoundUp(WriteOffset + ChunkLocation.Size, PayloadAlignment); - m_TotalSize.fetch_add(WriteOffset - OldOffset, std::memory_order::relaxed); - } - Chunk.clear(); - if (NewBlockFile) - { - ZEN_ASSERT_SLOW(NewBlockFile->IsOpen()); - NewBlockFile->Flush(); - } - } - - const ChunkIndexArray& DeleteMap = BlockDeleteChunks[ChunkMapIndex]; - for (size_t DeleteIndex : DeleteMap) - { - DeletedSize += ChunkLocations[DeleteIndex].Size; - } - - ChangeCallback(MovedChunks, DeleteMap); - MovedCount += MovedChunks.size(); - DeletedCount += DeleteMap.size(); - MovedChunks.clear(); - - if (OldBlockFile) - { - RwLock::ExclusiveLockScope __(m_InsertLock); - Stopwatch Timer; - const auto ___ = MakeGuard([&] { - uint64_t ElapsedUs = Timer.GetElapsedTimeUs(); - ReadBlockTimeUs += ElapsedUs; - ReadBlockLongestTimeUs = std::max(ElapsedUs, ReadBlockLongestTimeUs); - }); - - ZEN_DEBUG("marking cas block store file '{}' for delete, block #{}", OldBlockFile->GetPath(), BlockIndex); - ZEN_ASSERT(m_ChunkBlocks[BlockIndex] == OldBlockFile); - m_ChunkBlocks.erase(BlockIndex); - m_TotalSize.fetch_sub(OldBlockFile->TotalSize(), std::memory_order::relaxed); - OldBlockFile->MarkAsDeleteOnClose(); - } - } - if (NewBlockFile) - { - ZEN_ASSERT_SLOW(NewBlockFile->IsOpen()); - NewBlockFile->Flush(); - NewBlockFile = nullptr; - } - } - catch (const std::system_error& SystemError) - { - if (IsOOM(SystemError.code())) - { - ZEN_WARN("reclaiming space for '{}' ran out of memory: '{}'", m_BlocksBasePath, SystemError.what()); - } - else if (IsOOD(SystemError.code())) - { - ZEN_WARN("reclaiming space for '{}' ran out of disk space: '{}'", m_BlocksBasePath, SystemError.what()); - } - else - { - ZEN_ERROR("reclaiming space for '{}' failed with system error exception: '{}'", m_BlocksBasePath, SystemError.what()); - } - } - catch (const std::bad_alloc& BadAlloc) - { - ZEN_WARN("reclaiming space for '{}' ran out of memory: '{}'", m_BlocksBasePath, BadAlloc.what()); - } - catch (const std::exception& ex) - { - ZEN_ERROR("reclaiming space for '{}' failed with: '{}'", m_BlocksBasePath, ex.what()); - } -} - bool BlockStore::IterateBlock(std::span<const BlockStoreLocation> ChunkLocations, std::span<const size_t> InChunkIndexes, @@ -1945,53 +1502,6 @@ TEST_CASE("blockstore.chunks") CHECK(ReadChunkAsString(Store, ThirdChunkLocation) == ThirdChunkData); } -TEST_CASE("blockstore.clean.stray.blocks") -{ - using namespace blockstore::impl; - - ScopedTemporaryDirectory TempDir; - auto RootDirectory = TempDir.Path(); - - BlockStore Store; - Store.Initialize(RootDirectory / "store", 128, 1024); - - std::string FirstChunkData = "This is the data of the first chunk that we will write"; - BlockStoreLocation FirstChunkLocation = WriteStringAsChunk(Store, FirstChunkData, 4); - std::string SecondChunkData = "This is the data for the second chunk that we will write"; - BlockStoreLocation SecondChunkLocation = WriteStringAsChunk(Store, SecondChunkData, 4); - std::string ThirdChunkData = - "This is a much longer string that will not fit in the first block so it should be placed in the second block"; - BlockStoreLocation ThirdChunkLocation = WriteStringAsChunk(Store, ThirdChunkData, 4); - - Store.Close(); - - Store.Initialize(RootDirectory / "store", 128, 1024); - CHECK(GetDirectoryContent(RootDirectory / "store", true, false).size() == 2); - IoBuffer ThirdChunk = Store.TryGetChunk(ThirdChunkLocation); - CHECK(ThirdChunk); - - // Reclaim space should delete unreferenced block - Store.ReclaimSpace(Store.GetReclaimSnapshotState(), {FirstChunkLocation, SecondChunkLocation}, {0, 1}, 4, false); - // Block lives on as long as we reference it via ThirdChunk - CHECK(GetDirectoryContent(RootDirectory / "store", true, false).size() == 2); - ThirdChunk = {}; - CHECK(GetDirectoryContent(RootDirectory / "store", true, false).size() == 1); - ThirdChunk = Store.TryGetChunk(ThirdChunkLocation); - CHECK(!ThirdChunk); - - // Recreate a fake block for a missing chunk location - BlockStore::BlockIndexSet KnownBlocks; - KnownBlocks.insert(FirstChunkLocation.BlockIndex); - KnownBlocks.insert(SecondChunkLocation.BlockIndex); - KnownBlocks.insert(ThirdChunkLocation.BlockIndex); - Store.SyncExistingBlocksOnDisk(KnownBlocks); - - // We create a fake block for the location - we should still not be able to get the chunk - CHECK(GetDirectoryContent(RootDirectory / "store", true, false).size() == 2); - ThirdChunk = Store.TryGetChunk(ThirdChunkLocation); - CHECK(!ThirdChunk); -} - TEST_CASE("blockstore.flush.force.new.block") { using namespace blockstore::impl; @@ -2133,125 +1643,6 @@ TEST_CASE("blockstore.iterate.chunks") WorkLatch.Wait(); } -TEST_CASE("blockstore.reclaim.space") -{ - using namespace blockstore::impl; - - ScopedTemporaryDirectory TempDir; - auto RootDirectory = TempDir.Path(); - - BlockStore Store; - Store.Initialize(RootDirectory / "store", 512, 1024); - - constexpr size_t ChunkCount = 200; - constexpr size_t Alignment = 8; - std::vector<BlockStoreLocation> ChunkLocations; - std::vector<IoHash> ChunkHashes; - ChunkLocations.reserve(ChunkCount); - ChunkHashes.reserve(ChunkCount); - for (size_t ChunkIndex = 0; ChunkIndex < ChunkCount; ++ChunkIndex) - { - IoBuffer Chunk = CreateRandomBlob(57 + ChunkIndex); - - Store.WriteChunk(Chunk.Data(), Chunk.Size(), Alignment, [&](const BlockStoreLocation& L) { ChunkLocations.push_back(L); }); - ChunkHashes.push_back(IoHash::HashBuffer(Chunk.Data(), Chunk.Size())); - } - - std::vector<size_t> ChunksToKeep; - ChunksToKeep.reserve(ChunkLocations.size()); - for (size_t ChunkIndex = 0; ChunkIndex < ChunkCount; ++ChunkIndex) - { - ChunksToKeep.push_back(ChunkIndex); - } - - Store.Flush(/*ForceNewBlock*/ false); - BlockStore::ReclaimSnapshotState State1 = Store.GetReclaimSnapshotState(); - Store.ReclaimSpace(State1, ChunkLocations, ChunksToKeep, Alignment, true); - - // If we keep all the chunks we should not get any callbacks on moved/deleted stuff - Store.ReclaimSpace( - State1, - ChunkLocations, - ChunksToKeep, - Alignment, - false, - [](const BlockStore::MovedChunksArray&, const BlockStore::ChunkIndexArray&) { CHECK(false); }, - []() { - CHECK(false); - return 0; - }); - - size_t DeleteChunkCount = 38; - ChunksToKeep.clear(); - for (size_t ChunkIndex = DeleteChunkCount; ChunkIndex < ChunkCount; ++ChunkIndex) - { - ChunksToKeep.push_back(ChunkIndex); - } - - std::vector<BlockStoreLocation> NewChunkLocations = ChunkLocations; - size_t MovedChunkCount = 0; - size_t DeletedChunkCount = 0; - Store.ReclaimSpace( - State1, - ChunkLocations, - ChunksToKeep, - Alignment, - false, - [&](const BlockStore::MovedChunksArray& MovedChunks, const BlockStore::ChunkIndexArray& DeletedChunks) { - for (const auto& MovedChunk : MovedChunks) - { - CHECK(MovedChunk.first >= DeleteChunkCount); - NewChunkLocations[MovedChunk.first] = MovedChunk.second; - } - MovedChunkCount += MovedChunks.size(); - for (size_t DeletedIndex : DeletedChunks) - { - CHECK(DeletedIndex < DeleteChunkCount); - } - DeletedChunkCount += DeletedChunks.size(); - }, - []() { - CHECK(false); - return 0; - }); - CHECK(MovedChunkCount <= DeleteChunkCount); - CHECK(DeletedChunkCount == DeleteChunkCount); - ChunkLocations = std::vector<BlockStoreLocation>(NewChunkLocations.begin() + DeleteChunkCount, NewChunkLocations.end()); - - for (size_t ChunkIndex = 0; ChunkIndex < ChunkCount; ++ChunkIndex) - { - IoBuffer ChunkBlock = Store.TryGetChunk(NewChunkLocations[ChunkIndex]); - if (ChunkIndex >= DeleteChunkCount) - { - IoBuffer VerifyChunk = Store.TryGetChunk(NewChunkLocations[ChunkIndex]); - CHECK(VerifyChunk); - IoHash VerifyHash = IoHash::HashBuffer(VerifyChunk.Data(), VerifyChunk.Size()); - CHECK(VerifyHash == ChunkHashes[ChunkIndex]); - } - } - - // We need to take a new state since reclaim space add new block when compacting - BlockStore::ReclaimSnapshotState State2 = Store.GetReclaimSnapshotState(); - NewChunkLocations = ChunkLocations; - MovedChunkCount = 0; - DeletedChunkCount = 0; - Store.ReclaimSpace( - State2, - ChunkLocations, - {}, - Alignment, - false, - [&](const BlockStore::MovedChunksArray& MovedChunks, const BlockStore::ChunkIndexArray& DeletedChunks) { - CHECK(MovedChunks.empty()); - DeletedChunkCount += DeletedChunks.size(); - }, - []() { - CHECK(false); - return 0; - }); - CHECK(DeletedChunkCount == ChunkCount - DeleteChunkCount); -} - TEST_CASE("blockstore.thread.read.write") { using namespace blockstore::impl; @@ -2411,12 +1802,11 @@ TEST_CASE("blockstore.compact.blocks") } SUBCASE("keep current write block") { - uint64_t PreSize = Store.TotalSize(); - BlockStoreCompactState State; - BlockStore::ReclaimSnapshotState SnapshotState = Store.GetReclaimSnapshotState(); + uint64_t PreSize = Store.TotalSize(); + BlockStoreCompactState State; for (const BlockStoreLocation& Location : ChunkLocations) { - if (SnapshotState.m_ActiveWriteBlocks.contains(Location.BlockIndex)) + if (Store.IsWriting(Location.BlockIndex)) { continue; } @@ -2440,9 +1830,8 @@ TEST_CASE("blockstore.compact.blocks") { Store.Flush(true); - uint64_t PreSize = Store.TotalSize(); - BlockStoreCompactState State; - BlockStore::ReclaimSnapshotState SnapshotState = Store.GetReclaimSnapshotState(); + uint64_t PreSize = Store.TotalSize(); + BlockStoreCompactState State; for (const BlockStoreLocation& Location : ChunkLocations) { State.AddKeepLocation(Location); @@ -2462,11 +1851,10 @@ TEST_CASE("blockstore.compact.blocks") } SUBCASE("drop first block") { - uint64_t PreSize = Store.TotalSize(); - BlockStoreCompactState State; - BlockStore::ReclaimSnapshotState SnapshotState = Store.GetReclaimSnapshotState(); + uint64_t PreSize = Store.TotalSize(); + BlockStoreCompactState State; - CHECK(!SnapshotState.m_ActiveWriteBlocks.contains(0)); + CHECK(!Store.IsWriting(0)); State.IncludeBlock(0); uint64_t FirstBlockSize = 0; @@ -2496,11 +1884,10 @@ TEST_CASE("blockstore.compact.blocks") } SUBCASE("compact first block") { - uint64_t PreSize = Store.TotalSize(); - BlockStoreCompactState State; - BlockStore::ReclaimSnapshotState SnapshotState = Store.GetReclaimSnapshotState(); + uint64_t PreSize = Store.TotalSize(); + BlockStoreCompactState State; - CHECK(!SnapshotState.m_ActiveWriteBlocks.contains(0)); + CHECK(!Store.IsWriting(0)); State.IncludeBlock(0); uint64_t SkipChunkCount = 2; @@ -2555,14 +1942,13 @@ TEST_CASE("blockstore.compact.blocks") } SUBCASE("compact every other item") { - uint64_t PreSize = Store.TotalSize(); - BlockStoreCompactState State; - BlockStore::ReclaimSnapshotState SnapshotState = Store.GetReclaimSnapshotState(); - bool SkipFlag = false; + uint64_t PreSize = Store.TotalSize(); + BlockStoreCompactState State; + bool SkipFlag = false; for (const BlockStoreLocation& Location : ChunkLocations) { - if (SnapshotState.m_ActiveWriteBlocks.contains(Location.BlockIndex)) + if (Store.IsWriting(Location.BlockIndex)) { continue; } @@ -2579,7 +1965,7 @@ TEST_CASE("blockstore.compact.blocks") std::vector<BlockStoreLocation> DroppedLocations; for (const BlockStoreLocation& Location : ChunkLocations) { - if (SnapshotState.m_ActiveWriteBlocks.contains(Location.BlockIndex)) + if (Store.IsWriting(Location.BlockIndex)) { continue; } @@ -2616,7 +2002,7 @@ TEST_CASE("blockstore.compact.blocks") for (size_t Index = 0; Index < ChunkLocations.size(); Index++) { const BlockStoreLocation& Location = ChunkLocations[Index]; - if (SkipFlag && !SnapshotState.m_ActiveWriteBlocks.contains(Location.BlockIndex)) + if (SkipFlag && !Store.IsWriting(Location.BlockIndex)) { CHECK(std::find(DroppedLocations.begin(), DroppedLocations.end(), Location) != DroppedLocations.end()); CHECK(!Store.TryGetChunk(Location)); |