aboutsummaryrefslogtreecommitdiff
path: root/src/zenstore/blockstore.cpp
diff options
context:
space:
mode:
authorDan Engelbrecht <[email protected]>2024-10-03 16:42:57 +0200
committerGitHub Enterprise <[email protected]>2024-10-03 16:42:57 +0200
commitb13b5f48bb497aaf9f9f3d74aceb6e474cf12898 (patch)
tree24b1ed63ece11fb773a0ecf41ce6308969468198 /src/zenstore/blockstore.cpp
parent5.5.9-pre0 (diff)
downloadzen-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.cpp648
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));