diff options
| author | Dan Engelbrecht <[email protected]> | 2022-05-01 23:31:35 +0200 |
|---|---|---|
| committer | Dan Engelbrecht <[email protected]> | 2022-05-01 23:31:35 +0200 |
| commit | 08a0dc388f98e6d3eb8387b983a9a7fb959fe603 (patch) | |
| tree | 5f4bef8e81e55e22f65690250c84d943098c738b /zenstore/blockstore.cpp | |
| parent | remove m_TotalSize for blockstore (diff) | |
| download | zen-08a0dc388f98e6d3eb8387b983a9a7fb959fe603.tar.xz zen-08a0dc388f98e6d3eb8387b983a9a7fb959fe603.zip | |
reimplement CasContainerStrategy::Scrub
Diffstat (limited to 'zenstore/blockstore.cpp')
| -rw-r--r-- | zenstore/blockstore.cpp | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/zenstore/blockstore.cpp b/zenstore/blockstore.cpp index b4aa0f7c3..559dfc1ee 100644 --- a/zenstore/blockstore.cpp +++ b/zenstore/blockstore.cpp @@ -105,6 +105,12 @@ BlockStoreFile::Flush() m_File.Flush(); } +BasicFile& +BlockStoreFile::GetBasicFile() +{ + return m_File; +} + void BlockStoreFile::StreamByteRange(uint64_t FileOffset, uint64_t Size, std::function<void(const void* Data, uint64_t Size)>&& ChunkFun) { @@ -577,6 +583,82 @@ BlockStore::ReclaimSpace(const ReclaimSnapshotState& Snapshot, } } +void +BlockStore::IterateChunks(const std::vector<BlockStoreLocation>& ChunkLocations, + std::function<void(size_t ChunkIndex, const void* Data, uint64_t Size)> SmallChunkCallback, + std::function<void(size_t ChunkIndex, BasicFile& BlockFile, uint64_t Offset, uint64_t Size)> LargeChunkCallback) +{ + // We do a read sweep through the payloads file and validate + // any entries that are contained within each segment, with + // the assumption that most entries will be checked in this + // pass. An alternative strategy would be to use memory mapping. + + { + std::vector<size_t> BigChunks; + const uint64_t WindowSize = 4 * 1024 * 1024; + IoBuffer ReadBuffer{WindowSize}; + void* BufferBase = ReadBuffer.MutableData(); + + RwLock::SharedLockScope _(m_InsertLock); // TODO: Refactor so we don't have to keep m_InsertLock all the time? + + for (const auto& Block : m_ChunkBlocks) + { + uint64_t WindowStart = 0; + uint64_t WindowEnd = WindowSize; + uint32_t BlockIndex = Block.first; + const Ref<BlockStoreFile>& BlockFile = Block.second; + BlockFile->Open(); + const uint64_t FileSize = BlockFile->FileSize(); + + do + { + const uint64_t ChunkSize = Min(WindowSize, FileSize - WindowStart); + BlockFile->Read(BufferBase, ChunkSize, WindowStart); + + // TODO: We could be smarter here if the ChunkLocations were sorted on block index - we could + // then only scan a subset of ChunkLocations instead of scanning through them all... + for (size_t ChunkIndex = 0; ChunkIndex < ChunkLocations.size(); ++ChunkIndex) + { + const BlockStoreLocation Location = ChunkLocations[ChunkIndex]; + if (BlockIndex != Location.BlockIndex) + { + continue; + } + + const uint64_t EntryOffset = Location.Offset; + if ((EntryOffset >= WindowStart) && (EntryOffset < WindowEnd)) + { + const uint64_t EntryEnd = EntryOffset + Location.Size; + + if (EntryEnd >= WindowEnd) + { + BigChunks.push_back(ChunkIndex); + + continue; + } + + SmallChunkCallback(ChunkIndex, + reinterpret_cast<uint8_t*>(BufferBase) + Location.Offset - WindowStart, + Location.Size); + } + } + + WindowStart += WindowSize; + WindowEnd += WindowSize; + } while (WindowStart < FileSize); + } + + // Deal with large chunks + + for (size_t ChunkIndex : BigChunks) + { + const BlockStoreLocation Location = ChunkLocations[ChunkIndex]; + BasicFile& BlockFile = m_ChunkBlocks[Location.BlockIndex]->GetBasicFile(); + LargeChunkCallback(ChunkIndex, BlockFile, Location.Offset, Location.Size); + } + } +} + const char* BlockStore::GetBlockFileExtension() { |