From 14d7568f9c7d970b7bbf7b6463a0a8530f98bb6f Mon Sep 17 00:00:00 2001 From: Stefan Boberg Date: Wed, 20 Sep 2023 15:22:03 +0200 Subject: VFS implementation for local storage service (#396) currently, only Windows (using Projected File System) is supported --- src/zenserver/projectstore/projectstore.cpp | 110 ++++++++++++++++++++++++++-- 1 file changed, 102 insertions(+), 8 deletions(-) (limited to 'src/zenserver/projectstore/projectstore.cpp') diff --git a/src/zenserver/projectstore/projectstore.cpp b/src/zenserver/projectstore/projectstore.cpp index 9be600e4e..1ad4403f4 100644 --- a/src/zenserver/projectstore/projectstore.cpp +++ b/src/zenserver/projectstore/projectstore.cpp @@ -691,6 +691,45 @@ ProjectStore::Oplog::FindChunk(Oid ChunkId) return {}; } +std::vector +ProjectStore::Oplog::GetAllChunksInfo() +{ + // First just capture all the chunk ids + + std::vector InfoArray; + + { + RwLock::SharedLockScope _(m_OplogLock); + + if (m_Storage) + { + const size_t NumEntries = m_FileMap.size() + m_ChunkMap.size(); + + InfoArray.reserve(NumEntries); + + for (const auto& Kv : m_FileMap) + { + InfoArray.push_back({.ChunkId = Kv.first}); + } + + for (const auto& Kv : m_ChunkMap) + { + InfoArray.push_back({.ChunkId = Kv.first}); + } + } + } + + for (ChunkInfo& Info : InfoArray) + { + if (IoBuffer Chunk = FindChunk(Info.ChunkId)) + { + Info.ChunkSize = Chunk.GetSize(); + } + } + + return InfoArray; +} + void ProjectStore::Oplog::IterateFileMap( std::function&& Fn) @@ -2055,6 +2094,49 @@ ProjectStore::GetProjectFiles(const std::string_view ProjectId, const std::strin return {HttpResponseCode::OK, {}}; } +std::pair +ProjectStore::GetProjectChunks(const std::string_view ProjectId, const std::string_view OplogId, CbObject& OutPayload) +{ + ZEN_TRACE_CPU("ProjectStore::GetProjectChunks"); + + using namespace std::literals; + + Ref Project = OpenProject(ProjectId); + if (!Project) + { + return {HttpResponseCode::NotFound, fmt::format("unknown project '{}'", ProjectId)}; + } + Project->TouchProject(); + + ProjectStore::Oplog* FoundLog = Project->OpenOplog(OplogId); + if (!FoundLog) + { + return {HttpResponseCode::NotFound, fmt::format("unknown oplog '{}/{}'", ProjectId, OplogId)}; + } + Project->TouchOplog(OplogId); + + std::vector ChunkInfo = FoundLog->GetAllChunksInfo(); + + CbObjectWriter Response; + + Response.BeginArray("chunks"sv); + for (ProjectStore::Oplog::ChunkInfo& Info : ChunkInfo) + { + Response << Info.ChunkId; + } + Response.EndArray(); + + Response.BeginArray("sizes"sv); + for (ProjectStore::Oplog::ChunkInfo& Info : ChunkInfo) + { + Response << Info.ChunkSize; + } + Response.EndArray(); + + OutPayload = Response.Save(); + return {HttpResponseCode::OK, {}}; +} + std::pair ProjectStore::GetChunkInfo(const std::string_view ProjectId, const std::string_view OplogId, @@ -2119,6 +2201,25 @@ ProjectStore::GetChunkRange(const std::string_view ProjectId, uint64_t Size, ZenContentType AcceptType, IoBuffer& OutChunk) +{ + if (ChunkId.size() != 2 * sizeof(Oid::OidBits)) + { + return {HttpResponseCode::BadRequest, fmt::format("Chunk request for invalid chunk id '{}/{}'/'{}'", ProjectId, OplogId, ChunkId)}; + } + + const Oid Obj = Oid::FromHexString(ChunkId); + + return GetChunkRange(ProjectId, OplogId, Obj, Offset, Size, AcceptType, OutChunk); +} + +std::pair +ProjectStore::GetChunkRange(const std::string_view ProjectId, + const std::string_view OplogId, + Oid ChunkId, + uint64_t Offset, + uint64_t Size, + ZenContentType AcceptType, + IoBuffer& OutChunk) { bool IsOffset = Offset != 0 || Size != ~(0ull); @@ -2136,14 +2237,7 @@ ProjectStore::GetChunkRange(const std::string_view ProjectId, } Project->TouchOplog(OplogId); - if (ChunkId.size() != 2 * sizeof(Oid::OidBits)) - { - return {HttpResponseCode::BadRequest, fmt::format("Chunk request for invalid chunk id '{}/{}'/'{}'", ProjectId, OplogId, ChunkId)}; - } - - const Oid Obj = Oid::FromHexString(ChunkId); - - IoBuffer Chunk = FoundLog->FindChunk(Obj); + IoBuffer Chunk = FoundLog->FindChunk(ChunkId); if (!Chunk) { return {HttpResponseCode::NotFound, {}}; -- cgit v1.2.3