summaryrefslogtreecommitdiff
path: root/src/buildtool/execution_api/execution_service/bytestream_server.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/buildtool/execution_api/execution_service/bytestream_server.cpp')
-rw-r--r--src/buildtool/execution_api/execution_service/bytestream_server.cpp26
1 files changed, 25 insertions, 1 deletions
diff --git a/src/buildtool/execution_api/execution_service/bytestream_server.cpp b/src/buildtool/execution_api/execution_service/bytestream_server.cpp
index ada2e13f..32adba91 100644
--- a/src/buildtool/execution_api/execution_service/bytestream_server.cpp
+++ b/src/buildtool/execution_api/execution_service/bytestream_server.cpp
@@ -22,6 +22,8 @@
#include "fmt/core.h"
#include "src/buildtool/compatibility/native_support.hpp"
#include "src/buildtool/execution_api/common/bytestream_common.hpp"
+#include "src/buildtool/execution_api/execution_service/cas_utils.hpp"
+#include "src/buildtool/file_system/file_system_manager.hpp"
#include "src/buildtool/logging/log_level.hpp"
#include "src/buildtool/storage/garbage_collector.hpp"
#include "src/utils/cpp/tmp_dir.hpp"
@@ -157,9 +159,31 @@ auto BytestreamServiceImpl::Write(
} while (not request.finish_write() and reader->Read(&request));
}
+ // Before storing a tree, we have to verify that its parts are present
+ bool const is_tree = NativeSupport::IsTree(*hash);
+ if (is_tree) {
+ // ... unfortunately, this requires us to read the whole tree object
+ // into memory
+ auto content = FileSystemManager::ReadFile(tmp);
+ if (not content) {
+ auto const msg = fmt::format(
+ "Failed to read temporary file {} for {}", tmp.string(), *hash);
+ logger_.Emit(LogLevel::Error, "{}", msg);
+ return ::grpc::Status{::grpc::StatusCode::INTERNAL, msg};
+ }
+
+ ArtifactDigest dgst{NativeSupport::Unprefix(*hash), 0, true};
+ if (auto err = CASUtils::EnsureTreeInvariant(
+ static_cast<bazel_re::Digest>(dgst), *content, storage_)) {
+ auto const str = fmt::format("Write: {}", *std::move(err));
+ logger_.Emit(LogLevel::Error, "{}", str);
+ return ::grpc::Status{grpc::StatusCode::FAILED_PRECONDITION, str};
+ }
+ }
+
// Store blob and verify hash
std::optional<bazel_re::Digest> stored;
- if (NativeSupport::IsTree(*hash)) {
+ if (is_tree) {
stored = storage_.CAS().StoreTree</*kOwner=*/true>(tmp);
}
else {