summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/buildtool/serve_api/serve_service/source_tree.cpp73
-rw-r--r--src/buildtool/serve_api/serve_service/source_tree.hpp11
2 files changed, 84 insertions, 0 deletions
diff --git a/src/buildtool/serve_api/serve_service/source_tree.cpp b/src/buildtool/serve_api/serve_service/source_tree.cpp
index 8351d8d9..4ce09983 100644
--- a/src/buildtool/serve_api/serve_service/source_tree.cpp
+++ b/src/buildtool/serve_api/serve_service/source_tree.cpp
@@ -684,3 +684,76 @@ auto SourceTreeService::ServeArchiveTree(
request->sync_tree(),
response);
}
+
+auto SourceTreeService::ServeContent(
+ ::grpc::ServerContext* /* context */,
+ const ::justbuild::just_serve::ServeContentRequest* request,
+ ServeContentResponse* response) -> ::grpc::Status {
+ auto const& content{request->content()};
+ // acquire lock for CAS
+ auto lock = GarbageCollector::SharedLock();
+ if (!lock) {
+ auto str = fmt::format("Could not acquire gc SharedLock");
+ logger_->Emit(LogLevel::Error, str);
+ response->set_status(ServeContentResponse::INTERNAL_ERROR);
+ return ::grpc::Status::OK;
+ }
+ // check if content blob is in Git cache
+ if (auto data =
+ GetBlobFromRepo(StorageConfig::GitRoot(), content, logger_)) {
+ // upload blob to remote CAS
+ auto digest = ArtifactDigest{content, 0, /*is_tree=*/false};
+ auto repo = RepositoryConfig{};
+ if (not repo.SetGitCAS(StorageConfig::GitRoot())) {
+ auto str = fmt::format("Failed to SetGitCAS at {}",
+ StorageConfig::GitRoot().string());
+ logger_->Emit(LogLevel::Error, str);
+ response->set_status(ServeContentResponse::INTERNAL_ERROR);
+ return ::grpc::Status::OK;
+ }
+ auto git_api = GitApi{&repo};
+ if (not git_api.RetrieveToCas(
+ {Artifact::ObjectInfo{.digest = digest,
+ .type = ObjectType::File}},
+ &(*remote_api_))) {
+ auto str = fmt::format("Failed to sync content {}", content);
+ logger_->Emit(LogLevel::Error, str);
+ response->set_status(ServeContentResponse::SYNC_ERROR);
+ return ::grpc::Status::OK;
+ }
+ // success!
+ response->set_status(ServeContentResponse::OK);
+ return ::grpc::Status::OK;
+ }
+ // check if content blob is in a known repository
+ for (auto const& path : RemoteServeConfig::KnownRepositories()) {
+ if (auto data = GetBlobFromRepo(path, content, logger_)) {
+ // upload blob to remote CAS
+ auto digest = ArtifactDigest{content, 0, /*is_tree=*/false};
+ auto repo = RepositoryConfig{};
+ if (not repo.SetGitCAS(path)) {
+ auto str = fmt::format("Failed to SetGitCAS at {}",
+ StorageConfig::GitRoot().string());
+ logger_->Emit(LogLevel::Error, str);
+ response->set_status(ServeContentResponse::INTERNAL_ERROR);
+ return ::grpc::Status::OK;
+ }
+ auto git_api = GitApi{&repo};
+ if (not git_api.RetrieveToCas(
+ {Artifact::ObjectInfo{.digest = digest,
+ .type = ObjectType::File}},
+ &(*remote_api_))) {
+ auto str = fmt::format("Failed to sync content {}", content);
+ logger_->Emit(LogLevel::Error, str);
+ response->set_status(ServeContentResponse::SYNC_ERROR);
+ return ::grpc::Status::OK;
+ }
+ // success!
+ response->set_status(ServeContentResponse::OK);
+ return ::grpc::Status::OK;
+ }
+ }
+ // content blob not known
+ response->set_status(ServeContentResponse::NOT_FOUND);
+ return ::grpc::Status::OK;
+}
diff --git a/src/buildtool/serve_api/serve_service/source_tree.hpp b/src/buildtool/serve_api/serve_service/source_tree.hpp
index 030d33ee..db64d693 100644
--- a/src/buildtool/serve_api/serve_service/source_tree.hpp
+++ b/src/buildtool/serve_api/serve_service/source_tree.hpp
@@ -41,6 +41,8 @@ class SourceTreeService final
using ServeArchiveTreeResponse =
::justbuild::just_serve::ServeArchiveTreeResponse;
+ using ServeContentResponse = ::justbuild::just_serve::ServeContentResponse;
+
// Retrieve the Git-subtree identifier from a given Git commit.
//
// There are no method-specific errors.
@@ -58,6 +60,15 @@ class SourceTreeService final
const ::justbuild::just_serve::ServeArchiveTreeRequest* request,
ServeArchiveTreeResponse* response) -> ::grpc::Status override;
+ // Make the blob identifier of an archive content available in
+ // remote CAS, if blob is known.
+ //
+ // There are no method-specific errors.
+ auto ServeContent(
+ ::grpc::ServerContext* context,
+ const ::justbuild::just_serve::ServeContentRequest* request,
+ ServeContentResponse* response) -> ::grpc::Status override;
+
private:
mutable std::shared_mutex mutex_;
std::shared_ptr<Logger> logger_{std::make_shared<Logger>("serve-service")};