aboutsummaryrefslogtreecommitdiff
path: root/zenstore/blockstore.cpp
diff options
context:
space:
mode:
authorDan Engelbrecht <[email protected]>2022-05-01 23:31:35 +0200
committerDan Engelbrecht <[email protected]>2022-05-01 23:31:35 +0200
commit08a0dc388f98e6d3eb8387b983a9a7fb959fe603 (patch)
tree5f4bef8e81e55e22f65690250c84d943098c738b /zenstore/blockstore.cpp
parentremove m_TotalSize for blockstore (diff)
downloadzen-08a0dc388f98e6d3eb8387b983a9a7fb959fe603.tar.xz
zen-08a0dc388f98e6d3eb8387b983a9a7fb959fe603.zip
reimplement CasContainerStrategy::Scrub
Diffstat (limited to 'zenstore/blockstore.cpp')
-rw-r--r--zenstore/blockstore.cpp82
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()
{