summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/buildtool/storage/large_object_cas.hpp28
-rw-r--r--src/buildtool/storage/large_object_cas.tpp11
-rw-r--r--src/buildtool/storage/local_cas.hpp3
-rw-r--r--src/buildtool/storage/local_cas.tpp36
4 files changed, 29 insertions, 49 deletions
diff --git a/src/buildtool/storage/large_object_cas.hpp b/src/buildtool/storage/large_object_cas.hpp
index ec8f64db..0fbb161a 100644
--- a/src/buildtool/storage/large_object_cas.hpp
+++ b/src/buildtool/storage/large_object_cas.hpp
@@ -17,7 +17,6 @@
#include <cstdint>
#include <filesystem>
-#include <memory>
#include <optional>
#include <string>
#include <utility>
@@ -70,29 +69,6 @@ class LargeObjectError final {
std::string message_;
};
-/// \brief Stores a temporary directory containing a result of splicing.
-class LargeObject final {
- public:
- explicit LargeObject(StorageConfig const& storage_config) noexcept
- : directory_(storage_config.CreateTypedTmpDir("splice")),
- path_(directory_ ? directory_->GetPath() / "result" : ".") {}
-
- /// \brief Check whether the large object is valid.
- [[nodiscard]] auto IsValid() const noexcept -> bool {
- return directory_ != nullptr;
- }
-
- /// \brief Obtain the path to the spliced result.
- [[nodiscard]] auto GetPath() const noexcept
- -> std::filesystem::path const& {
- return path_;
- }
-
- private:
- TmpDir::Ptr directory_;
- std::filesystem::path path_;
-};
-
/// \brief Stores auxiliary information for reconstructing large objects.
/// The entries are keyed by the hash of the spliced result and the value of an
/// entry is the concatenation of the hashes of chunks the large object is
@@ -144,7 +120,7 @@ class LargeObjectCAS final {
/// \return A temporary directory that contains a single file
/// "result" on success or an error on failure.
[[nodiscard]] auto TrySplice(ArtifactDigest const& digest) const noexcept
- -> expected<LargeObject, LargeObjectError>;
+ -> expected<TmpFile::Ptr, LargeObjectError>;
/// \brief Splice an object from parts. This method doesn't check whether
/// the result of splicing is already in the CAS.
@@ -154,7 +130,7 @@ class LargeObjectCAS final {
/// "result" on success or an error on failure.
[[nodiscard]] auto Splice(ArtifactDigest const& digest,
std::vector<ArtifactDigest> const& parts)
- const noexcept -> expected<LargeObject, LargeObjectError>;
+ const noexcept -> expected<TmpFile::Ptr, LargeObjectError>;
/// \brief Uplink large entry from this generation to latest LocalCAS
/// generation. For the large entry it's parts get promoted first and then
diff --git a/src/buildtool/storage/large_object_cas.tpp b/src/buildtool/storage/large_object_cas.tpp
index 5b8daa32..6e69a0c9 100644
--- a/src/buildtool/storage/large_object_cas.tpp
+++ b/src/buildtool/storage/large_object_cas.tpp
@@ -184,7 +184,7 @@ auto LargeObjectCAS<kDoGlobalUplink, kType>::Split(ArtifactDigest const& digest)
template <bool kDoGlobalUplink, ObjectType kType>
auto LargeObjectCAS<kDoGlobalUplink, kType>::TrySplice(
ArtifactDigest const& digest) const noexcept
- -> expected<LargeObject, LargeObjectError> {
+ -> expected<TmpFile::Ptr, LargeObjectError> {
auto parts = ReadEntry(digest);
if (not parts) {
return unexpected{LargeObjectError{
@@ -198,10 +198,11 @@ template <bool kDoGlobalUplink, ObjectType kType>
auto LargeObjectCAS<kDoGlobalUplink, kType>::Splice(
ArtifactDigest const& digest,
std::vector<ArtifactDigest> const& parts) const noexcept
- -> expected<LargeObject, LargeObjectError> {
+ -> expected<TmpFile::Ptr, LargeObjectError> {
// Create temporary space for splicing:
- LargeObject large_object(storage_config_);
- if (not large_object.IsValid()) {
+ TmpFile::Ptr large_object = TmpDir::CreateFile(
+ storage_config_.CreateTypedTmpDir("splice"), /*file_name=*/"result");
+ if (large_object == nullptr) {
return unexpected{LargeObjectError{
LargeObjectErrorCode::Internal,
fmt::format("could not create a temporary space for {}",
@@ -210,7 +211,7 @@ auto LargeObjectCAS<kDoGlobalUplink, kType>::Splice(
// Splice the object from parts
try {
- std::ofstream stream(large_object.GetPath());
+ std::ofstream stream(large_object->GetPath());
for (auto const& part : parts) {
auto part_path = local_cas_.BlobPath(part, /*is_executable=*/false);
if (not part_path) {
diff --git a/src/buildtool/storage/local_cas.hpp b/src/buildtool/storage/local_cas.hpp
index de63a008..01eab944 100644
--- a/src/buildtool/storage/local_cas.hpp
+++ b/src/buildtool/storage/local_cas.hpp
@@ -32,6 +32,7 @@
#include "src/buildtool/storage/large_object_cas.hpp" // IWYU pragma: keep
#include "src/buildtool/storage/uplinker.hpp"
#include "src/utils/cpp/expected.hpp"
+#include "src/utils/cpp/tmp_dir.hpp"
/// \brief The local (logical) CAS for storing blobs and trees.
/// Blobs can be stored/queried as executable or non-executable. Trees might be
@@ -344,7 +345,7 @@ class LocalCAS {
template <ObjectType kType, bool kIsLocalGeneration = not kDoGlobalUplink>
requires(kIsLocalGeneration)
[[nodiscard]] auto TrySplice(ArtifactDigest const& digest) const noexcept
- -> std::optional<LargeObject>;
+ -> TmpFile::Ptr;
template <ObjectType kType>
[[nodiscard]] auto Splice(ArtifactDigest const& digest,
diff --git a/src/buildtool/storage/local_cas.tpp b/src/buildtool/storage/local_cas.tpp
index 7a096eb9..7cc6bea0 100644
--- a/src/buildtool/storage/local_cas.tpp
+++ b/src/buildtool/storage/local_cas.tpp
@@ -45,7 +45,7 @@ auto LocalCAS<kDoGlobalUplink>::LocalUplinkBlob(
// Determine blob path of given generation.
auto blob_path = skip_sync ? BlobPathNoSync(digest, is_executable)
: BlobPath(digest, is_executable);
- std::optional<LargeObject> spliced;
+ TmpFile::Ptr spliced;
if (not blob_path) {
spliced = TrySplice<ObjectType::File>(digest);
blob_path = spliced ? std::optional{spliced->GetPath()} : std::nullopt;
@@ -54,7 +54,7 @@ auto LocalCAS<kDoGlobalUplink>::LocalUplinkBlob(
return false;
}
- if (spliced) {
+ if (spliced != nullptr) {
// The result of uplinking of a large object must not affect the
// result of uplinking in general. In other case, two sequential calls
// to BlobPath might return different results: The first call splices
@@ -67,7 +67,7 @@ auto LocalCAS<kDoGlobalUplink>::LocalUplinkBlob(
}
// Uplink blob from older generation to the latest generation.
- if (spliced and is_executable) {
+ if (spliced != nullptr and is_executable) {
// During multithreaded splicing, the main process can be forked
// (inheriting open file descriptors). In this case, an executable file
// saved using hardlinking becomes inaccessible. To prevent this,
@@ -108,10 +108,11 @@ auto LocalCAS<kDoGlobalUplink>::LocalUplinkGitTree(
// Determine tree path of given generation.
auto tree_path = cas_tree_.BlobPath(digest);
- std::optional<LargeObject> spliced;
+ TmpFile::Ptr spliced;
if (not tree_path) {
spliced = TrySplice<ObjectType::Tree>(digest);
- tree_path = spliced ? std::optional{spliced->GetPath()} : std::nullopt;
+ tree_path = spliced != nullptr ? std::optional{spliced->GetPath()}
+ : std::nullopt;
}
if (not tree_path) {
return false;
@@ -123,11 +124,12 @@ auto LocalCAS<kDoGlobalUplink>::LocalUplinkGitTree(
[this](std::vector<ArtifactDigest> const& ids) -> bool {
for (auto const& id : ids) {
auto link_path = cas_file_.BlobPath(id);
- std::optional<LargeObject> spliced;
+ TmpFile::Ptr spliced;
if (not link_path) {
spliced = TrySplice<ObjectType::File>(id);
- link_path =
- spliced ? std::optional{spliced->GetPath()} : std::nullopt;
+ link_path = spliced != nullptr
+ ? std::optional{spliced->GetPath()}
+ : std::nullopt;
}
if (not link_path) {
return false;
@@ -175,7 +177,7 @@ auto LocalCAS<kDoGlobalUplink>::LocalUplinkGitTree(
}
}
- if (spliced) {
+ if (spliced != nullptr) {
// Uplink the large entry afterwards:
// The result of uplinking of a large object must not affect the
// result of uplinking in general. In other case, two sequential calls
@@ -208,10 +210,11 @@ auto LocalCAS<kDoGlobalUplink>::LocalUplinkBazelDirectory(
// Determine bazel directory path of given generation.
auto dir_path = cas_tree_.BlobPath(digest);
- std::optional<LargeObject> spliced;
+ TmpFile::Ptr spliced;
if (not dir_path) {
spliced = TrySplice<ObjectType::Tree>(digest);
- dir_path = spliced ? std::optional{spliced->GetPath()} : std::nullopt;
+ dir_path = spliced != nullptr ? std::optional{spliced->GetPath()}
+ : std::nullopt;
}
if (not dir_path) {
return false;
@@ -248,7 +251,7 @@ auto LocalCAS<kDoGlobalUplink>::LocalUplinkBazelDirectory(
// Determine bazel directory path in latest generation.
auto const dir_path_latest = latest.cas_tree_.BlobPath(digest);
- if (spliced) {
+ if (spliced != nullptr) {
// Uplink the large entry afterwards:
// The result of uplinking of a large object must not affect the
// result of uplinking in general. In other case, two sequential
@@ -259,7 +262,7 @@ auto LocalCAS<kDoGlobalUplink>::LocalUplinkBazelDirectory(
std::ignore = LocalUplinkLargeObject<ObjectType::Tree>(latest, digest);
}
- bool const skip_store = spliced and not splice_result;
+ bool const skip_store = spliced != nullptr and not splice_result;
// Uplink bazel directory from older generation to the latest
// generation.
if (skip_store or dir_path_latest.has_value() or
@@ -295,11 +298,10 @@ template <bool kDoGlobalUplink>
template <ObjectType kType, bool kIsLocalGeneration>
requires(kIsLocalGeneration)
auto LocalCAS<kDoGlobalUplink>::TrySplice(
- ArtifactDigest const& digest) const noexcept -> std::optional<LargeObject> {
+ ArtifactDigest const& digest) const noexcept -> TmpFile::Ptr {
auto spliced = IsTreeObject(kType) ? cas_tree_large_.TrySplice(digest)
: cas_file_large_.TrySplice(digest);
- return spliced and spliced->IsValid() ? std::optional{std::move(*spliced)}
- : std::nullopt;
+ return spliced.has_value() ? spliced.value() : nullptr;
}
template <bool kDoGlobalUplink>
@@ -399,7 +401,7 @@ auto LocalCAS<kDoGlobalUplink>::Splice(ArtifactDigest const& digest,
// decide whether the result is valid is unreasonable, because these
// methods can refer to a file that existed before. The direct hash
// calculation is done instead.
- auto const& file_path = large_object.GetPath();
+ auto const& file_path = large_object->GetPath();
auto spliced_digest =
ArtifactDigestFactory::HashFileAs<kType>(hash_function_, file_path);
if (not spliced_digest) {