diff options
| author | Dan Engelbrecht <[email protected]> | 2023-10-05 16:03:14 +0200 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-10-05 16:03:14 +0200 |
| commit | ba22ffd43e646fe035f8457f3a89500c1cb1c120 (patch) | |
| tree | 87535bbcc78683c6eabaaf4d27b90da9aeb94077 /src/zenstore/blockstore.cpp | |
| parent | Fix curruption of disk cache bucket index on GC (#448) (diff) | |
| download | zen-ba22ffd43e646fe035f8457f3a89500c1cb1c120.tar.xz zen-ba22ffd43e646fe035f8457f3a89500c1cb1c120.zip | |
check that block does not exists on disk before starting write to it (#449)
* check that block does not exists on disk before starting write to it
Diffstat (limited to 'src/zenstore/blockstore.cpp')
| -rw-r--r-- | src/zenstore/blockstore.cpp | 62 |
1 files changed, 44 insertions, 18 deletions
diff --git a/src/zenstore/blockstore.cpp b/src/zenstore/blockstore.cpp index 968e919d6..12ea24752 100644 --- a/src/zenstore/blockstore.cpp +++ b/src/zenstore/blockstore.cpp @@ -266,6 +266,38 @@ BlockStore::Close() m_BlocksBasePath.clear(); } +uint32_t +BlockStore::GetFreeBlockIndex(uint32_t ProbeIndex, RwLock::ExclusiveLockScope&, std::filesystem::path& OutBlockPath) const +{ + if (m_ChunkBlocks.size() == m_MaxBlockCount) + { + return (uint32_t)m_MaxBlockCount; + } + + while (true) + { + if (!m_ChunkBlocks.contains(ProbeIndex)) + { + OutBlockPath = GetBlockPath(m_BlocksBasePath, ProbeIndex); + std::error_code Ec; + bool Exists = std::filesystem::exists(OutBlockPath, Ec); + if (Ec) + { + ZEN_WARN("Failed to probe existence of file '{}' when trying to allocate a new block. Reason: '{}'", + OutBlockPath, + Ec.message()); + return (uint32_t)m_MaxBlockCount; + } + if (!Exists) + { + return ProbeIndex; + } + } + ProbeIndex = (ProbeIndex + 1) & (m_MaxBlockCount - 1); + } + return ProbeIndex; +} + void BlockStore::WriteChunk(const void* Data, uint64_t Size, uint64_t Alignment, const WriteChunkCallback& Callback) { @@ -288,19 +320,14 @@ BlockStore::WriteChunk(const void* Data, uint64_t Size, uint64_t Alignment, cons m_WriteBlock = nullptr; } - if (m_ChunkBlocks.size() == m_MaxBlockCount) - { - throw std::runtime_error(fmt::format("unable to allocate a new block in '{}'", m_BlocksBasePath)); - } - WriteBlockIndex += IsWriting ? 1 : 0; - while (m_ChunkBlocks.contains(WriteBlockIndex)) + std::filesystem::path BlockPath; + WriteBlockIndex = GetFreeBlockIndex(WriteBlockIndex, InsertLock, BlockPath); + if (WriteBlockIndex == (uint32_t)m_MaxBlockCount) { - WriteBlockIndex = (WriteBlockIndex + 1) & (m_MaxBlockCount - 1); + throw std::runtime_error(fmt::format("unable to allocate a new block in '{}'", m_BlocksBasePath)); } - std::filesystem::path BlockPath = GetBlockPath(m_BlocksBasePath, WriteBlockIndex); - Ref<BlockStoreFile> NewBlockFile(new BlockStoreFile(BlockPath)); NewBlockFile->Create(m_MaxBlockSize); @@ -616,27 +643,26 @@ BlockStore::ReclaimSpace(const ReclaimSnapshotState& Snapshot, ChangeCallback(MovedChunks, {}); MovedCount += KeepMap.size(); MovedChunks.clear(); - RwLock::ExclusiveLockScope __(m_InsertLock); + RwLock::ExclusiveLockScope InsertLock(m_InsertLock); Stopwatch Timer; const auto ___ = MakeGuard([&] { uint64_t ElapsedUs = Timer.GetElapsedTimeUs(); ReadBlockTimeUs += ElapsedUs; ReadBlockLongestTimeUs = std::max(ElapsedUs, ReadBlockLongestTimeUs); }); - if (m_ChunkBlocks.size() == m_MaxBlockCount) + + 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; } - while (m_ChunkBlocks.contains(NextBlockIndex)) - { - NextBlockIndex = (NextBlockIndex + 1) & (m_MaxBlockCount - 1); - } - std::filesystem::path NewBlockPath = GetBlockPath(m_BlocksBasePath, NextBlockIndex); - NewBlockFile = new BlockStoreFile(NewBlockPath); - m_ChunkBlocks[NextBlockIndex] = NewBlockFile; + + NewBlockFile = new BlockStoreFile(NewBlockPath); + m_ChunkBlocks[NextBlockIndex] = NewBlockFile; } std::error_code Error; |