diff options
| author | Stefan Boberg <[email protected]> | 2021-05-17 23:49:23 +0200 |
|---|---|---|
| committer | Stefan Boberg <[email protected]> | 2021-05-17 23:49:23 +0200 |
| commit | 8e97d0a9d6446ebe185262b65611b17a7541d48a (patch) | |
| tree | 6148925139f086cce5d96a6af628e311f18f6cd7 /zenserver/projectstore.cpp | |
| parent | HTTP: added some basic comments to httpserver.h (diff) | |
| download | zen-8e97d0a9d6446ebe185262b65611b17a7541d48a.tar.xz zen-8e97d0a9d6446ebe185262b65611b17a7541d48a.zip | |
Added oplog prep step to avoid redundant chunk transfers
Diffstat (limited to 'zenserver/projectstore.cpp')
| -rw-r--r-- | zenserver/projectstore.cpp | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/zenserver/projectstore.cpp b/zenserver/projectstore.cpp index dcad483a6..0d7ad0f16 100644 --- a/zenserver/projectstore.cpp +++ b/zenserver/projectstore.cpp @@ -1039,6 +1039,59 @@ HttpProjectService::HttpProjectService(CasStore& Store, ProjectStore* Projects) HttpVerb::kGet | HttpVerb::kHead); m_Router.RegisterRoute( + "{project}/oplog/{log}/prep", + [this](HttpRouterRequest& Req) { + HttpServerRequest& HttpReq = Req.ServerRequest(); + + const auto& ProjectId = Req.GetCapture(1); + const auto& OplogId = Req.GetCapture(2); + + ProjectStore::Oplog* FoundLog = m_ProjectStore->OpenProjectOplog(ProjectId, OplogId); + + if (FoundLog == nullptr) + { + return HttpReq.WriteResponse(HttpResponse::NotFound); + } + + ProjectStore::Oplog& Log = *FoundLog; + + // This operation takes a list of referenced hashes and decides which + // chunks are not present on this server. This list is then returned in + // the "need" list in the response + + IoBuffer Payload = HttpReq.ReadPayload(); + CbObject RequestObject = LoadCompactBinaryObject(Payload); + + std::vector<IoHash> NeedList; + + for (auto Entry : RequestObject["have"sv]) + { + const IoHash FileHash = Entry.AsHash(); + + if (!m_CasStore.FindChunk(FileHash)) + { + spdlog::debug("NEED: {}", FileHash); + + NeedList.push_back(FileHash); + } + } + + CbObjectWriter Cbo; + Cbo.BeginArray("need"); + + for (const IoHash& Hash : NeedList) + { + Cbo << Hash; + } + + Cbo.EndArray(); + CbObject Response = Cbo.Save(); + + return HttpReq.WriteResponse(HttpResponse::OK, Response); + }, + HttpVerb::kPost); + + m_Router.RegisterRoute( "{project}/oplog/{log}/new", [this](HttpRouterRequest& Req) { HttpServerRequest& HttpReq = Req.ServerRequest(); @@ -1057,6 +1110,13 @@ HttpProjectService::HttpProjectService(CasStore& Store, ProjectStore* Projects) IoBuffer Payload = HttpReq.ReadPayload(); + // This will attempt to open files which may not exist for the case where + // the prep step rejected the chunk. This should be fixed since there's + // a performance cost associated with any file system activity + + bool IsValid = true; + std::vector<IoHash> MissingChunks; + CbPackage::AttachmentResolver Resolver = [&](const IoHash& Hash) -> SharedBuffer { std::filesystem::path AttachmentPath = Log.TempPath() / Hash.ToHexString(); @@ -1064,8 +1124,15 @@ HttpProjectService::HttpProjectService(CasStore& Store, ProjectStore* Projects) { return SharedBuffer(std::move(Data)); } + else if (Data = m_CasStore.FindChunk(Hash)) + { + return SharedBuffer(std::move(Data)); + } else { + IsValid = false; + MissingChunks.push_back(Hash); + return {}; } }; @@ -1073,6 +1140,13 @@ HttpProjectService::HttpProjectService(CasStore& Store, ProjectStore* Projects) CbPackage Package; Package.Load(Payload, &UniqueBuffer::Alloc, &Resolver); + if (!IsValid) + { + // TODO: emit diagnostics identifying missing chunks + + return HttpReq.WriteResponse(HttpResponse::NotFound, HttpContentType::kText, "Missing chunk reference"); + } + CbObject Core = Package.GetObject(); if (!Core["key"sv]) |