diff options
| author | Dan Engelbrecht <[email protected]> | 2024-03-28 14:01:22 +0100 |
|---|---|---|
| committer | GitHub Enterprise <[email protected]> | 2024-03-28 14:01:22 +0100 |
| commit | 04f1b48b006373ac82ae23a947dcb048d56cf63f (patch) | |
| tree | 905aa41750e8b60700b2c0a2ae516a4a1702f4c1 /src | |
| parent | Faster reading of compressed buffer headers by not materializing entire sourc... (diff) | |
| download | zen-04f1b48b006373ac82ae23a947dcb048d56cf63f.tar.xz zen-04f1b48b006373ac82ae23a947dcb048d56cf63f.zip | |
add "fieldnames" query param for GetProjectFiles/GetProjectChunkInfos (#29)
- Improvement: It is now possible to control which fields to include in `/prj/{project}/oplog/{log}/chunkinfos` request by adding a comma delimited list of filed names for `fieldnames` parameter
- Default fields are: `id`, `rawhash` and `rawsize` (translates to `?fieldnames=id,rawhash,rawsize`)
- Use `?fieldnames=*` to get all the fields
- Improvement: It is now possible to control which fields to include in `/prj/{project}/oplog/{log}/files` request by adding a comma delimited list of filed names for `fieldnames` parameter
- Default fields are: `id`, `clientpath` and `serverpath` (translates to `?fieldnames=id,clientpath,serverpath`), `filter=client` only applies if `fieldnames` is not given as a parameter
- Use `?fieldnames=*` to get all the fields
Diffstat (limited to 'src')
| -rw-r--r-- | src/zenserver/projectstore/httpprojectstore.cpp | 48 | ||||
| -rw-r--r-- | src/zenserver/projectstore/projectstore.cpp | 97 | ||||
| -rw-r--r-- | src/zenserver/projectstore/projectstore.h | 15 |
3 files changed, 137 insertions, 23 deletions
diff --git a/src/zenserver/projectstore/httpprojectstore.cpp b/src/zenserver/projectstore/httpprojectstore.cpp index e8a748c4c..f2bf5b353 100644 --- a/src/zenserver/projectstore/httpprojectstore.cpp +++ b/src/zenserver/projectstore/httpprojectstore.cpp @@ -621,10 +621,31 @@ HttpProjectService::HandleFilesRequest(HttpRouterRequest& Req) HttpServerRequest::QueryParams Params = HttpReq.GetQueryParams(); - const bool FilterClient = Params.GetValue("filter"sv) == "client"sv; + std::unordered_set<std::string> WantedFieldNames; + if (auto FieldFilter = HttpServerRequest::Decode(Params.GetValue("fieldnames")); !FieldFilter.empty()) + { + if (FieldFilter != "*") // Get all - empty FieldFilter equal getting all fields + { + ForEachStrTok(FieldFilter, ',', [&](std::string_view FieldName) { + WantedFieldNames.insert(std::string(FieldName)); + return true; + }); + } + } + else + { + const bool FilterClient = Params.GetValue("filter"sv) == "client"sv; + WantedFieldNames.insert("id"); + WantedFieldNames.insert("clientpath"); + if (!FilterClient) + { + WantedFieldNames.insert("serverpath"); + } + } CbObject ResponsePayload; - std::pair<HttpResponseCode, std::string> Result = m_ProjectStore->GetProjectFiles(ProjectId, OplogId, FilterClient, ResponsePayload); + std::pair<HttpResponseCode, std::string> Result = + m_ProjectStore->GetProjectFiles(ProjectId, OplogId, WantedFieldNames, ResponsePayload); if (Result.first == HttpResponseCode::OK) { if (HttpReq.AcceptContentType() == HttpContentType::kCompressedBinary) @@ -666,8 +687,29 @@ HttpProjectService::HandleChunkInfosRequest(HttpRouterRequest& Req) const auto& ProjectId = Req.GetCapture(1); const auto& OplogId = Req.GetCapture(2); + HttpServerRequest::QueryParams Params = HttpReq.GetQueryParams(); + + std::unordered_set<std::string> WantedFieldNames; + if (auto FieldFilter = HttpServerRequest::Decode(Params.GetValue("fieldnames")); !FieldFilter.empty()) + { + if (FieldFilter != "*") // Get all - empty FieldFilter equal getting all fields + { + ForEachStrTok(FieldFilter, ',', [&](std::string_view FieldName) { + WantedFieldNames.insert(std::string(FieldName)); + return true; + }); + } + } + else + { + WantedFieldNames.insert("id"); + WantedFieldNames.insert("rawhash"); + WantedFieldNames.insert("rawsize"); + } + CbObject ResponsePayload; - std::pair<HttpResponseCode, std::string> Result = m_ProjectStore->GetProjectChunkInfos(ProjectId, OplogId, ResponsePayload); + std::pair<HttpResponseCode, std::string> Result = + m_ProjectStore->GetProjectChunkInfos(ProjectId, OplogId, WantedFieldNames, ResponsePayload); if (Result.first == HttpResponseCode::OK) { if (HttpReq.AcceptContentType() == HttpContentType::kCompressedBinary) diff --git a/src/zenserver/projectstore/projectstore.cpp b/src/zenserver/projectstore/projectstore.cpp index 3d8004be3..f01134fa5 100644 --- a/src/zenserver/projectstore/projectstore.cpp +++ b/src/zenserver/projectstore/projectstore.cpp @@ -2501,7 +2501,10 @@ ProjectStore::GetProjectsList() } std::pair<HttpResponseCode, std::string> -ProjectStore::GetProjectFiles(const std::string_view ProjectId, const std::string_view OplogId, bool FilterClient, CbObject& OutPayload) +ProjectStore::GetProjectFiles(const std::string_view ProjectId, + const std::string_view OplogId, + const std::unordered_set<std::string>& WantedFieldNames, + CbObject& OutPayload) { ZEN_TRACE_CPU("Store::GetProjectFiles"); @@ -2521,17 +2524,53 @@ ProjectStore::GetProjectFiles(const std::string_view ProjectId, const std::strin } Project->TouchOplog(OplogId); + const bool WantsAllFields = WantedFieldNames.empty(); + + const bool WantsIdField = WantsAllFields || WantedFieldNames.contains("id"); + const bool WantsClientPathField = WantsAllFields || WantedFieldNames.contains("clientpath"); + const bool WantsServerPathField = WantsAllFields || WantedFieldNames.contains("serverpath"); + const bool WantsRawSizeField = WantsAllFields || WantedFieldNames.contains("rawsize"); + const bool WantsSizeField = WantsAllFields || WantedFieldNames.contains("size"); + CbObjectWriter Response; Response.BeginArray("files"sv); FoundLog->IterateFileMap([&](const Oid& Id, const std::string_view& ServerPath, const std::string_view& ClientPath) { Response.BeginObject(); - Response << "id"sv << Id; - Response << "clientpath"sv << ClientPath; - if (!FilterClient && !ServerPath.empty()) + if (WantsIdField) + { + Response << "id"sv << Id; + } + if (WantsClientPathField) + { + Response << "clientpath"sv << ClientPath; + } + if (WantsServerPathField && !ServerPath.empty()) { Response << "serverpath"sv << ServerPath; } + if (WantsRawSizeField || WantsSizeField) + { + IoBuffer Chunk = FoundLog->FindChunk(Id); + if (WantsSizeField) + { + Response << "size"sv << Chunk.GetSize(); + } + if (WantsRawSizeField) + { + if (Chunk.GetContentType() == ZenContentType::kCompressedBinary) + { + IoHash _; + uint64_t RawSize = 0; + (void)CompressedBuffer::FromCompressed(SharedBuffer(Chunk), _, RawSize); + Response << "rawsize"sv << RawSize; + } + else + { + Response << "rawsize"sv << Chunk.GetSize(); + } + } + } Response.EndObject(); }); @@ -2541,7 +2580,10 @@ ProjectStore::GetProjectFiles(const std::string_view ProjectId, const std::strin } std::pair<HttpResponseCode, std::string> -ProjectStore::GetProjectChunkInfos(const std::string_view ProjectId, const std::string_view OplogId, CbObject& OutPayload) +ProjectStore::GetProjectChunkInfos(const std::string_view ProjectId, + const std::string_view OplogId, + const std::unordered_set<std::string>& WantedFieldNames, + CbObject& OutPayload) { ZEN_TRACE_CPU("ProjectStore::GetProjectChunkInfos"); @@ -2564,25 +2606,54 @@ ProjectStore::GetProjectChunkInfos(const std::string_view ProjectId, const std:: std::vector<std::pair<Oid, IoHash>> ChunkInfos; FoundLog->IterateChunkMap([&ChunkInfos](const Oid& Id, const IoHash& Hash) { ChunkInfos.push_back({Id, Hash}); }); + const bool WantsAllFields = WantedFieldNames.empty(); + + const bool WantsIdField = WantsAllFields || WantedFieldNames.contains("id"); + const bool WantsRawHashField = WantsAllFields || WantedFieldNames.contains("rawhash"); + const bool WantsRawSizeField = WantsAllFields || WantedFieldNames.contains("rawsize"); + const bool WantsSizeField = WantsAllFields || WantedFieldNames.contains("size"); + CbObjectWriter Response; Response.BeginArray("chunkinfos"sv); for (const auto& ChunkInfo : ChunkInfos) { - if (IoBuffer Chunk = FoundLog->FindChunk(ChunkInfo.first)) + Response.BeginObject(); + if (WantsIdField) { - Response.BeginObject(); Response << "id"sv << ChunkInfo.first; + } + if (WantsRawHashField) + { Response << "rawhash"sv << ChunkInfo.second; - uint64_t RawSize = Chunk.GetSize(); - if (Chunk.GetContentType() == ZenContentType::kCompressedBinary) + } + + if (WantsRawSizeField || WantsSizeField) + { + if (IoBuffer Chunk = FoundLog->FindChunk(ChunkInfo.first)) { - IoHash _; - (void)CompressedBuffer::FromCompressed(SharedBuffer(Chunk), _, RawSize); + uint64_t Size = Chunk.GetSize(); + if (WantsSizeField) + { + Response << "size"sv << Size; + } + if (WantsRawSizeField) + { + if (Chunk.GetContentType() == ZenContentType::kCompressedBinary) + { + IoHash _; + uint64_t RawSize = 0; + (void)CompressedBuffer::FromCompressed(SharedBuffer(Chunk), _, RawSize); + Response << "rawsize"sv << RawSize; + } + else + { + Response << "rawsize"sv << Size; + } + } } - Response << "rawsize"sv << RawSize; - Response.EndObject(); } + Response.EndObject(); } Response.EndArray(); diff --git a/src/zenserver/projectstore/projectstore.h b/src/zenserver/projectstore/projectstore.h index 191dcf1f8..e07853ca8 100644 --- a/src/zenserver/projectstore/projectstore.h +++ b/src/zenserver/projectstore/projectstore.h @@ -316,13 +316,14 @@ public: virtual std::vector<GcReferenceChecker*> CreateReferenceCheckers(GcCtx& Ctx) override; CbArray GetProjectsList(); - std::pair<HttpResponseCode, std::string> GetProjectFiles(const std::string_view ProjectId, - const std::string_view OplogId, - bool FilterClient, - CbObject& OutPayload); - std::pair<HttpResponseCode, std::string> GetProjectChunkInfos(const std::string_view ProjectId, - const std::string_view OplogId, - CbObject& OutPayload); + std::pair<HttpResponseCode, std::string> GetProjectFiles(const std::string_view ProjectId, + const std::string_view OplogId, + const std::unordered_set<std::string>& WantedFieldNames, + CbObject& OutPayload); + std::pair<HttpResponseCode, std::string> GetProjectChunkInfos(const std::string_view ProjectId, + const std::string_view OplogId, + const std::unordered_set<std::string>& WantedFieldNames, + CbObject& OutPayload); std::pair<HttpResponseCode, std::string> GetChunkInfo(const std::string_view ProjectId, const std::string_view OplogId, const std::string_view ChunkId, |