aboutsummaryrefslogtreecommitdiff
path: root/src/zenserver/storage/projectstore
diff options
context:
space:
mode:
Diffstat (limited to 'src/zenserver/storage/projectstore')
-rw-r--r--src/zenserver/storage/projectstore/httpprojectstore.cpp244
1 files changed, 152 insertions, 92 deletions
diff --git a/src/zenserver/storage/projectstore/httpprojectstore.cpp b/src/zenserver/storage/projectstore/httpprojectstore.cpp
index 2fa10a292..03b8aa382 100644
--- a/src/zenserver/storage/projectstore/httpprojectstore.cpp
+++ b/src/zenserver/storage/projectstore/httpprojectstore.cpp
@@ -546,7 +546,7 @@ namespace {
Host.empty() ? OverrideHost : Host,
/*Quiet*/ false,
/*Unattended*/ false,
- /*Hidden*/ true);
+ /*Hidden*/ false);
TokenProviderMaybe)
{
TokenProvider = TokenProviderMaybe.value();
@@ -636,18 +636,6 @@ namespace {
return Result;
}
- std::pair<HttpResponseCode, std::string> ConvertResult(const RemoteProjectStore::Result& Result)
- {
- if (Result.ErrorCode == 0)
- {
- return {HttpResponseCode::OK, Result.Text};
- }
- return {static_cast<HttpResponseCode>(Result.ErrorCode),
- Result.Reason.empty() ? Result.Text
- : Result.Text.empty() ? Result.Reason
- : fmt::format("{}: {}", Result.Reason, Result.Text)};
- }
-
static uint64_t GetMaxMemoryBufferSize(size_t MaxBlockSize, bool BoostWorkerMemory)
{
return BoostWorkerMemory ? (MaxBlockSize + 16u * 1024u) : 1024u * 1024u;
@@ -2671,44 +2659,38 @@ HttpProjectService::HandleOplogLoadRequest(HttpRouterRequest& Req)
WorkerThreadPool& WorkerPool = GetLargeWorkerPool(EWorkloadType::Background);
- RemoteProjectStore::LoadContainerResult ContainerResult = BuildContainer(
- m_CidStore,
- *Project,
- *Oplog,
- WorkerPool,
- MaxBlockSize,
- MaxChunkEmbedSize,
- MaxChunksPerBlock,
- ChunkFileSizeLimit,
- /* BuildBlocks */ false,
- /* IgnoreMissingAttachments */ false,
- /* AllowChunking*/ false,
- [](CompressedBuffer&&, ChunkBlockDescription&&) {},
- [](const IoHash&, TGetAttachmentBufferFunc&&) {},
- [](std::vector<std::pair<IoHash, FetchChunkFunc>>&&) {},
- /* EmbedLooseFiles*/ false);
-
- if (ContainerResult.ErrorCode == 0)
- {
- return HttpReq.WriteResponse(HttpResponseCode::OK, ContainerResult.ContainerObject);
- }
- else
- {
- ZEN_DEBUG("Request {}: '{}' failed with {}. Reason: `{}`",
- ToString(HttpReq.RequestVerb()),
- HttpReq.QueryString(),
- ContainerResult.ErrorCode,
- ContainerResult.Reason);
-
- if (ContainerResult.Reason.empty())
+ try
+ {
+ CbObject ContainerObject = BuildContainer(
+ m_CidStore,
+ *Project,
+ *Oplog,
+ WorkerPool,
+ MaxBlockSize,
+ MaxChunksPerBlock,
+ MaxChunkEmbedSize,
+ ChunkFileSizeLimit,
+ /* BuildBlocks */ false,
+ /* IgnoreMissingAttachments */ false,
+ /* AllowChunking*/ false,
+ [](CompressedBuffer&&, ChunkBlockDescription&&) {},
+ [](const IoHash&, TGetAttachmentBufferFunc&&) {},
+ [](std::vector<std::pair<IoHash, FetchChunkFunc>>&&) {},
+ /* EmbedLooseFiles*/ false);
+ return HttpReq.WriteResponse(HttpResponseCode::OK, ContainerObject);
+ }
+ catch (const HttpClientError& HttpEx)
+ {
+ if (HttpEx.GetInternalErrorCode() != HttpClientErrorCode::kOK)
{
- return HttpReq.WriteResponse(HttpResponseCode(ContainerResult.ErrorCode));
+ return HttpReq.WriteResponse(HttpResponseCode::InternalServerError, HttpContentType::kText, HttpEx.what());
}
else
{
- return HttpReq.WriteResponse(HttpResponseCode(ContainerResult.ErrorCode), HttpContentType::kText, ContainerResult.Reason);
+ return HttpReq.WriteResponse(HttpEx.GetHttpResponseCode(), HttpContentType::kText, HttpEx.what());
}
}
+ // Let server request handler deal with other exceptions
}
void
@@ -2872,32 +2854,70 @@ HttpProjectService::HandleRpcRequest(HttpRouterRequest& Req)
WorkerThreadPool& NetworkWorkerPool = Workers->GetNetworkPool();
Context.ReportMessage(fmt::format("{}", Workers->GetWorkersInfo()));
- RemoteProjectStore::Result Result = LoadOplog(LoadOplogContext{
- .ChunkStore = m_CidStore,
- .RemoteStore = *RemoteStoreResult->Store,
- .OptionalCache = RemoteStoreResult->OptionalCache ? RemoteStoreResult->OptionalCache->Cache.get() : nullptr,
- .CacheBuildId = RemoteStoreResult->OptionalCache ? RemoteStoreResult->OptionalCache->BuildsId : Oid::Zero,
- .OptionalCacheStats = RemoteStoreResult->OptionalCache ? &RemoteStoreResult->OptionalCache->Stats : nullptr,
- .Oplog = *Oplog,
- .NetworkWorkerPool = NetworkWorkerPool,
- .WorkerPool = WorkerPool,
- .ForceDownload = Force,
- .IgnoreMissingAttachments = IgnoreMissingAttachments,
- .CleanOplog = CleanOplog,
- .PartialBlockRequestMode = PartialBlockRequestMode,
- .PopulateCache = RemoteStoreResult->OptionalCache ? RemoteStoreResult->OptionalCache->Populate : false,
- .StoreLatencySec = RemoteStoreResult->LatencySec,
- .StoreMaxRangeCountPerRequest = RemoteStoreResult->MaxRangeCountPerRequest,
- .CacheLatencySec = RemoteStoreResult->OptionalCache ? RemoteStoreResult->OptionalCache->LatencySec : -1.0,
- .CacheMaxRangeCountPerRequest =
- RemoteStoreResult->OptionalCache ? RemoteStoreResult->OptionalCache->MaxRangeCountPerRequest : 0,
- .OptionalJobContext = &Context});
- auto Response = ConvertResult(Result);
- ZEN_INFO("LoadOplog: Status: {} '{}'", ToString(Response.first), Response.second);
- if (!IsHttpSuccessCode(Response.first))
+
+ try
{
- throw JobError(Response.second.empty() ? fmt::format("Status: {}", ToString(Response.first)) : Response.second,
- (int)Response.first);
+ LoadOplog(LoadOplogContext{
+ .ChunkStore = m_CidStore,
+ .RemoteStore = *RemoteStoreResult->Store,
+ .OptionalCache = RemoteStoreResult->OptionalCache ? RemoteStoreResult->OptionalCache->Cache.get() : nullptr,
+ .CacheBuildId = RemoteStoreResult->OptionalCache ? RemoteStoreResult->OptionalCache->BuildsId : Oid::Zero,
+ .OptionalCacheStats = RemoteStoreResult->OptionalCache ? &RemoteStoreResult->OptionalCache->Stats : nullptr,
+ .Oplog = *Oplog,
+ .NetworkWorkerPool = NetworkWorkerPool,
+ .WorkerPool = WorkerPool,
+ .ForceDownload = Force,
+ .IgnoreMissingAttachments = IgnoreMissingAttachments,
+ .CleanOplog = CleanOplog,
+ .PartialBlockRequestMode = PartialBlockRequestMode,
+ .PopulateCache = RemoteStoreResult->OptionalCache ? RemoteStoreResult->OptionalCache->Populate : false,
+ .StoreLatencySec = RemoteStoreResult->LatencySec,
+ .StoreMaxRangeCountPerRequest = RemoteStoreResult->MaxRangeCountPerRequest,
+ .CacheLatencySec = RemoteStoreResult->OptionalCache ? RemoteStoreResult->OptionalCache->LatencySec : -1.0,
+ .CacheMaxRangeCountPerRequest =
+ RemoteStoreResult->OptionalCache ? RemoteStoreResult->OptionalCache->MaxRangeCountPerRequest : 0,
+ .OptionalJobContext = &Context});
+ }
+ catch (const HttpClientError& HttpEx)
+ {
+ if (HttpEx.GetInternalErrorCode() != HttpClientErrorCode::kOK)
+ {
+ throw JobError(fmt::format("Failed due to an http exception (Err: {}): {}",
+ static_cast<int>(HttpEx.GetInternalErrorCode()),
+ HttpEx.what()),
+ static_cast<int>(HttpEx.GetResponseClass()));
+ }
+ else
+ {
+ throw JobError(fmt::format("Failed due to an http exception (Status: {}): {}",
+ static_cast<int>(HttpEx.GetHttpResponseCode()),
+ HttpEx.what()),
+ static_cast<int>(HttpEx.GetHttpResponseCode()));
+ }
+ }
+ catch (const AssertException& AssertEx)
+ {
+ throw JobError(fmt::format("Failed due to an assert exception: {}", AssertEx.FullDescription()),
+ static_cast<int>(HttpResponseCode::InternalServerError));
+ }
+ catch (const std::system_error& SysEx)
+ {
+ throw JobError(fmt::format("Failed due to a system error ({}): {}", SysEx.code().value(), SysEx.what()),
+ SysEx.code().value());
+ }
+ catch (const std::exception& Ex)
+ {
+ throw JobError(fmt::format("Failed due to an exception: {}", Ex.what()),
+ static_cast<int>(HttpResponseCode::InternalServerError));
+ }
+
+ if (Context.IsCancelled())
+ {
+ ZEN_INFO("LoadOplog: Operation cancelled");
+ }
+ else
+ {
+ ZEN_INFO("LoadOplog: Complete");
}
});
@@ -2961,26 +2981,63 @@ HttpProjectService::HandleRpcRequest(HttpRouterRequest& Req)
WorkerThreadPool& WorkerPool = Workers->GetIOWorkerPool();
WorkerThreadPool& NetworkWorkerPool = Workers->GetNetworkPool();
- RemoteProjectStore::Result Result = SaveOplog(m_CidStore,
- *ActualRemoteStore,
- *Project,
- *Oplog,
- NetworkWorkerPool,
- WorkerPool,
- MaxBlockSize,
- MaxChunksPerBlock,
- MaxChunkEmbedSize,
- ChunkFileSizeLimit,
- EmbedLooseFile,
- Force,
- IgnoreMissingAttachments,
- &Context);
- auto Response = ConvertResult(Result);
- ZEN_INFO("SaveOplog: Status: {} '{}'", ToString(Response.first), Response.second);
- if (!IsHttpSuccessCode(Response.first))
+ try
+ {
+ SaveOplog(m_CidStore,
+ *ActualRemoteStore,
+ *Project,
+ *Oplog,
+ NetworkWorkerPool,
+ WorkerPool,
+ MaxBlockSize,
+ MaxChunksPerBlock,
+ MaxChunkEmbedSize,
+ ChunkFileSizeLimit,
+ EmbedLooseFile,
+ Force,
+ IgnoreMissingAttachments,
+ &Context);
+ }
+ catch (const HttpClientError& HttpEx)
+ {
+ if (HttpEx.GetInternalErrorCode() != HttpClientErrorCode::kOK)
+ {
+ throw JobError(fmt::format("Failed due to an http exception (Err: {}): {}",
+ static_cast<int>(HttpEx.GetInternalErrorCode()),
+ HttpEx.what()),
+ static_cast<int>(HttpEx.GetResponseClass()));
+ }
+ else
+ {
+ throw JobError(fmt::format("Failed due to an http exception (Status: {}): {}",
+ static_cast<int>(HttpEx.GetHttpResponseCode()),
+ HttpEx.what()),
+ static_cast<int>(HttpEx.GetHttpResponseCode()));
+ }
+ }
+ catch (const AssertException& AssertEx)
+ {
+ throw JobError(fmt::format("Failed due to an assert exception: {}", AssertEx.FullDescription()),
+ static_cast<int>(HttpResponseCode::InternalServerError));
+ }
+ catch (const std::system_error& SysEx)
+ {
+ throw JobError(fmt::format("Failed due to a system error ({}): {}", SysEx.code().value(), SysEx.what()),
+ SysEx.code().value());
+ }
+ catch (const std::exception& Ex)
+ {
+ throw JobError(fmt::format("Failed due to an exception: {}", Ex.what()),
+ static_cast<int>(HttpResponseCode::InternalServerError));
+ }
+
+ if (Context.IsCancelled())
+ {
+ ZEN_INFO("SaveOplog: Operation cancelled");
+ }
+ else
{
- throw JobError(Response.second.empty() ? fmt::format("Status: {}", ToString(Response.first)) : Response.second,
- (int)Response.first);
+ ZEN_INFO("SaveOplog: Complete");
}
});
@@ -3104,8 +3161,10 @@ HttpProjectService::HandleRpcRequest(HttpRouterRequest& Req)
continue;
}
- std::error_code Ec;
- const std::filesystem::path FilePath = std::filesystem::canonical(Project->RootDir / ServerPath, Ec);
+ std::error_code Ec;
+ // Long paths require MakeSafeAbsolutePath otherwise canonical will yield an error code
+ const std::filesystem::path SafeAbsFilePath = MakeSafeAbsolutePath(Project->RootDir / ServerPath);
+ const std::filesystem::path FilePath = std::filesystem::canonical(SafeAbsFilePath, Ec);
if (Ec)
{
@@ -3126,7 +3185,8 @@ HttpProjectService::HandleRpcRequest(HttpRouterRequest& Req)
}
BasicFile DataFile;
- DataFile.Open(FilePath, BasicFile::Mode::kRead, Ec);
+ // Must use SafeAbsFilePath because canonical will have removed leading chars for handling long paths
+ DataFile.Open(SafeAbsFilePath, BasicFile::Mode::kRead, Ec);
if (Ec)
{