diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/buildtool/storage/large_object_cas.hpp | 28 | ||||
-rw-r--r-- | src/buildtool/storage/large_object_cas.tpp | 11 | ||||
-rw-r--r-- | src/buildtool/storage/local_cas.hpp | 3 | ||||
-rw-r--r-- | src/buildtool/storage/local_cas.tpp | 36 |
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) { |