diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/buildtool/storage/config.hpp | 44 | ||||
-rw-r--r-- | src/buildtool/storage/garbage_collector.cpp | 4 | ||||
-rw-r--r-- | src/buildtool/storage/large_object_cas.hpp | 15 | ||||
-rw-r--r-- | src/buildtool/storage/large_object_cas.tpp | 2 | ||||
-rw-r--r-- | src/buildtool/storage/local_ac.hpp | 9 | ||||
-rw-r--r-- | src/buildtool/storage/local_ac.tpp | 24 | ||||
-rw-r--r-- | src/buildtool/storage/local_cas.hpp | 16 | ||||
-rw-r--r-- | src/buildtool/storage/storage.hpp | 46 | ||||
-rw-r--r-- | src/buildtool/storage/target_cache.hpp | 14 | ||||
-rw-r--r-- | src/buildtool/storage/target_cache.tpp | 21 |
10 files changed, 113 insertions, 82 deletions
diff --git a/src/buildtool/storage/config.hpp b/src/buildtool/storage/config.hpp index 38cdc45a..417d3e88 100644 --- a/src/buildtool/storage/config.hpp +++ b/src/buildtool/storage/config.hpp @@ -27,6 +27,19 @@ #include "src/utils/cpp/gsl.hpp" #include "src/utils/cpp/tmp_dir.hpp" +class StorageConfig; + +struct GenerationConfig final { + gsl::not_null<StorageConfig const*> const storage_config; + std::filesystem::path const cas_f; + std::filesystem::path const cas_x; + std::filesystem::path const cas_t; + std::filesystem::path const cas_large_f; + std::filesystem::path const cas_large_t; + std::filesystem::path const action_cache; + std::filesystem::path const target_cache; +}; + /// \brief Global storage configuration. class StorageConfig { public: @@ -76,8 +89,7 @@ class StorageConfig { return BuildRoot() / "git"; } - /// \brief Root directory of specific storage generation for compatible and - /// non-compatible protocol types. + /// \brief Root directory of specific storage generation [[nodiscard]] auto GenerationCacheRoot(std::size_t index) const noexcept -> std::filesystem::path { ExpectsAudit(index < num_generations_); @@ -85,15 +97,6 @@ class StorageConfig { return CacheRoot() / generation; } - /// \brief Storage directory of specific generation and protocol type. - [[nodiscard]] auto GenerationCacheDir( - std::size_t index, - bool is_compatible = Compatibility::IsCompatible()) const noexcept - -> std::filesystem::path { - return UpdatePathForCompatibility(GenerationCacheRoot(index), - is_compatible); - } - /// \brief Root directory for all ephemeral directories, i.e., directories /// that can (and should) be removed immediately by garbage collection. [[nodiscard]] auto EphemeralRoot() const noexcept -> std::filesystem::path { @@ -115,6 +118,25 @@ class StorageConfig { return TmpDir::Create(parent_path); } + [[nodiscard]] auto CreateGenerationConfig( + std::size_t generation) const noexcept -> GenerationConfig { + bool const compatible = Compatibility::IsCompatible(); + auto const cache_root = GenerationCacheRoot(generation); + auto const cache_dir = + UpdatePathForCompatibility(cache_root, compatible); + + return GenerationConfig{ + .storage_config = this, + .cas_f = cache_dir / "casf", + .cas_x = cache_dir / "casx", + .cas_t = cache_dir / (compatible ? "casf" : "cast"), + .cas_large_f = cache_dir / "cas-large-f", + .cas_large_t = + cache_dir / (compatible ? "cas-large-f" : "cas-large-t"), + .action_cache = cache_dir / "ac", + .target_cache = cache_dir / "tc"}; + }; + private: // Build root directory. All the storage dirs are subdirs of build_root. // By default, build_root is set to $HOME/.cache/just. diff --git a/src/buildtool/storage/garbage_collector.cpp b/src/buildtool/storage/garbage_collector.cpp index ccb8b83c..76a225c3 100644 --- a/src/buildtool/storage/garbage_collector.cpp +++ b/src/buildtool/storage/garbage_collector.cpp @@ -312,8 +312,8 @@ auto GarbageCollector::Compactify(StorageConfig const& storage_config, // Compactification must be done for both native and compatible storages. auto compactify = [&storage_config, threshold](bool compatible) -> bool { Compatibility::SetCompatible(compatible); - auto const storage = - ::Generation(storage_config.GenerationCacheDir(0, compatible)); + auto gen_config = storage_config.CreateGenerationConfig(0); + auto const storage = ::Generation(gen_config); return Compactifier::RemoveInvalid(storage.CAS()) and Compactifier::RemoveSpliced(storage.CAS()) and diff --git a/src/buildtool/storage/large_object_cas.hpp b/src/buildtool/storage/large_object_cas.hpp index 86c00171..e442aa90 100644 --- a/src/buildtool/storage/large_object_cas.hpp +++ b/src/buildtool/storage/large_object_cas.hpp @@ -69,8 +69,8 @@ class LargeObjectError final { /// \brief Stores a temporary directory containing a result of splicing. class LargeObject final { public: - LargeObject() noexcept - : directory_(StorageConfig::Instance().CreateTypedTmpDir("splice")), + 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. @@ -96,9 +96,13 @@ class LargeObject final { template <bool kDoGlobalUplink, ObjectType kType> class LargeObjectCAS final { public: - LargeObjectCAS(LocalCAS<kDoGlobalUplink> const& local_cas, - std::filesystem::path const& store_path) noexcept - : local_cas_(local_cas), file_store_(store_path) {} + explicit LargeObjectCAS( + gsl::not_null<LocalCAS<kDoGlobalUplink> const*> const& local_cas, + GenerationConfig const& config) noexcept + : local_cas_(*local_cas), + file_store_(IsTreeObject(kType) ? config.cas_large_t + : config.cas_large_f), + storage_config_{*config.storage_config} {} LargeObjectCAS(LargeObjectCAS const&) = delete; LargeObjectCAS(LargeObjectCAS&&) = delete; @@ -167,6 +171,7 @@ class LargeObjectCAS final { kDoGlobalUplink ? StoreMode::LastWins : StoreMode::FirstWins; LocalCAS<kDoGlobalUplink> const& local_cas_; + StorageConfig const& storage_config_; FileStorage<ObjectType::File, kStoreMode, /*kSetEpochTime=*/false> file_store_; diff --git a/src/buildtool/storage/large_object_cas.tpp b/src/buildtool/storage/large_object_cas.tpp index d216c8e8..ca8ac8c0 100644 --- a/src/buildtool/storage/large_object_cas.tpp +++ b/src/buildtool/storage/large_object_cas.tpp @@ -194,7 +194,7 @@ auto LargeObjectCAS<kDoGlobalUplink, kType>::Splice( std::vector<bazel_re::Digest> const& parts) const noexcept -> expected<LargeObject, LargeObjectError> { // Create temporary space for splicing: - LargeObject large_object; + LargeObject large_object(storage_config_); if (not large_object.IsValid()) { return unexpected{LargeObjectError{ LargeObjectErrorCode::Internal, diff --git a/src/buildtool/storage/local_ac.hpp b/src/buildtool/storage/local_ac.hpp index 41f7b7ac..98061e8a 100644 --- a/src/buildtool/storage/local_ac.hpp +++ b/src/buildtool/storage/local_ac.hpp @@ -22,6 +22,7 @@ #include "src/buildtool/file_system/file_storage.hpp" #include "src/buildtool/file_system/file_system_manager.hpp" #include "src/buildtool/logging/logger.hpp" +#include "src/buildtool/storage/config.hpp" #include "src/buildtool/storage/garbage_collector.hpp" #include "src/buildtool/storage/local_cas.hpp" @@ -43,9 +44,9 @@ class LocalAC { /// Local AC generation used by GC without global uplink. using LocalGenerationAC = LocalAC</*kDoGlobalUplink=*/false>; - LocalAC(std::shared_ptr<LocalCAS<kDoGlobalUplink>> cas, - std::filesystem::path const& store_path) noexcept - : cas_{std::move(cas)}, file_store_{store_path} {}; + explicit LocalAC(gsl::not_null<LocalCAS<kDoGlobalUplink> const*> const& cas, + GenerationConfig const& config) noexcept + : cas_{*cas}, file_store_{config.action_cache} {}; LocalAC(LocalAC const&) = default; LocalAC(LocalAC&&) noexcept = default; @@ -88,7 +89,7 @@ class LocalAC { kDoGlobalUplink ? StoreMode::LastWins : StoreMode::FirstWins; std::shared_ptr<Logger> logger_{std::make_shared<Logger>("LocalAC")}; - gsl::not_null<std::shared_ptr<LocalCAS<kDoGlobalUplink>>> cas_; + LocalCAS<kDoGlobalUplink> const& cas_; FileStorage<ObjectType::File, kStoreMode, /*kSetEpochTime=*/false> file_store_; diff --git a/src/buildtool/storage/local_ac.tpp b/src/buildtool/storage/local_ac.tpp index 3f74d97e..38facf21 100644 --- a/src/buildtool/storage/local_ac.tpp +++ b/src/buildtool/storage/local_ac.tpp @@ -24,7 +24,7 @@ auto LocalAC<kDoGlobalUplink>::StoreResult( bazel_re::Digest const& action_id, bazel_re::ActionResult const& result) const noexcept -> bool { auto bytes = result.SerializeAsString(); - auto digest = cas_->StoreBlob(bytes); + auto digest = cas_.StoreBlob(bytes); return (digest and file_store_.AddFromBytes(NativeSupport::Unprefix(action_id.hash()), digest->SerializeAsString())); @@ -95,14 +95,14 @@ requires(kIsLocalGeneration) auto LocalAC<kDoGlobalUplink>::LocalUplinkEntry( // Uplink result content for (auto const& file : result->output_files()) { - if (not cas_->LocalUplinkBlob( - *latest.cas_, file.digest(), file.is_executable())) { + if (not cas_.LocalUplinkBlob( + latest.cas_, file.digest(), file.is_executable())) { return false; } } for (auto const& link : result->output_file_symlinks()) { - if (not cas_->LocalUplinkBlob( - *latest.cas_, + if (not cas_.LocalUplinkBlob( + latest.cas_, bazel_re::Digest( ArtifactDigest::Create<ObjectType::File>(link.target())), /*is_executable=*/false)) { @@ -110,8 +110,8 @@ requires(kIsLocalGeneration) auto LocalAC<kDoGlobalUplink>::LocalUplinkEntry( } } for (auto const& link : result->output_directory_symlinks()) { - if (not cas_->LocalUplinkBlob( - *latest.cas_, + if (not cas_.LocalUplinkBlob( + latest.cas_, bazel_re::Digest( ArtifactDigest::Create<ObjectType::File>(link.target())), /*is_executable=*/false)) { @@ -119,15 +119,15 @@ requires(kIsLocalGeneration) auto LocalAC<kDoGlobalUplink>::LocalUplinkEntry( } } for (auto const& directory : result->output_directories()) { - if (not cas_->LocalUplinkTree(*latest.cas_, directory.tree_digest())) { + if (not cas_.LocalUplinkTree(latest.cas_, directory.tree_digest())) { return false; } } // Uplink result (cache value) - if (not cas_->LocalUplinkBlob(*latest.cas_, - result_digest, - /*is_executable=*/false)) { + if (not cas_.LocalUplinkBlob(latest.cas_, + result_digest, + /*is_executable=*/false)) { return false; } @@ -140,7 +140,7 @@ template <bool kDoGlobalUplink> auto LocalAC<kDoGlobalUplink>::ReadResult(bazel_re::Digest const& digest) const noexcept -> std::optional<bazel_re::ActionResult> { bazel_re::ActionResult result{}; - if (auto src_path = cas_->BlobPath(digest, /*is_executable=*/false)) { + if (auto src_path = cas_.BlobPath(digest, /*is_executable=*/false)) { auto const bytes = FileSystemManager::ReadFile(*src_path); if (bytes.has_value() and result.ParseFromString(*bytes)) { return result; diff --git a/src/buildtool/storage/local_cas.hpp b/src/buildtool/storage/local_cas.hpp index b29c870b..64811a62 100644 --- a/src/buildtool/storage/local_cas.hpp +++ b/src/buildtool/storage/local_cas.hpp @@ -23,6 +23,7 @@ #include "gsl/gsl" #include "src/buildtool/file_system/git_repo.hpp" #include "src/buildtool/file_system/object_cas.hpp" +#include "src/buildtool/storage/config.hpp" #include "src/buildtool/storage/garbage_collector.hpp" #include "src/buildtool/storage/large_object_cas.hpp" #include "src/utils/cpp/expected.hpp" @@ -44,15 +45,12 @@ class LocalCAS { /// Note that the base path is concatenated by a single character /// 'f'/'x'/'t' for each internally used physical CAS. /// \param base The base path for the CAS. - explicit LocalCAS(std::filesystem::path const& base) - : cas_file_{base.string() + 'f', Uplinker<ObjectType::File>()}, - cas_exec_{base.string() + 'x', Uplinker<ObjectType::Executable>()}, - cas_tree_{base.string() + (Compatibility::IsCompatible() ? 'f' : 't'), - Uplinker<ObjectType::Tree>()}, - cas_file_large_{*this, base.string() + "-large-f"}, - cas_tree_large_{*this, - base.string() + "-large-" + - (Compatibility::IsCompatible() ? 'f' : 't')} {} + explicit LocalCAS(GenerationConfig const& config) + : cas_file_{config.cas_f, Uplinker<ObjectType::File>()}, + cas_exec_{config.cas_x, Uplinker<ObjectType::Executable>()}, + cas_tree_{config.cas_t, Uplinker<ObjectType::Tree>()}, + cas_file_large_{this, config}, + cas_tree_large_{this, config} {} /// \brief Obtain path to the storage root. /// \param type Type of the storage to be obtained. diff --git a/src/buildtool/storage/storage.hpp b/src/buildtool/storage/storage.hpp index 960699f1..ae56ef91 100644 --- a/src/buildtool/storage/storage.hpp +++ b/src/buildtool/storage/storage.hpp @@ -17,6 +17,7 @@ #include <cstddef> #include <filesystem> +#include <memory> #include <optional> #include <vector> @@ -37,34 +38,34 @@ template <bool kDoGlobalUplink> class LocalStorage { public: - explicit LocalStorage(std::filesystem::path const& storage_path) - : cas_{std::make_shared<LocalCAS<kDoGlobalUplink>>(storage_path / - "cas")}, - ac_{cas_, storage_path / "ac"}, - tc_{cas_, storage_path / "tc"} {} + static constexpr std::size_t kYoungest = 0U; + + using CAS_t = LocalCAS<kDoGlobalUplink>; + using AC_t = LocalAC<kDoGlobalUplink>; + using TC_t = ::TargetCache<kDoGlobalUplink>; + + explicit LocalStorage(GenerationConfig const& config) + : cas_{std::make_shared<CAS_t>(config)}, + ac_{std::make_shared<AC_t>(&*cas_, config)}, + tc_{std::make_shared<TC_t>(&*cas_, config)} {} /// \brief Get the CAS instance. - [[nodiscard]] auto CAS() const noexcept - -> LocalCAS<kDoGlobalUplink> const& { - return *cas_; - } + [[nodiscard]] auto CAS() const noexcept -> CAS_t const& { return *cas_; } /// \brief Get the action cache instance. - [[nodiscard]] auto ActionCache() const noexcept - -> LocalAC<kDoGlobalUplink> const& { - return ac_; + [[nodiscard]] auto ActionCache() const noexcept -> AC_t const& { + return *ac_; } /// \brief Get the target cache instance. - [[nodiscard]] auto TargetCache() const noexcept - -> TargetCache<kDoGlobalUplink> const& { - return tc_; + [[nodiscard]] auto TargetCache() const noexcept -> TC_t const& { + return *tc_; } private: - gsl::not_null<std::shared_ptr<LocalCAS<kDoGlobalUplink>>> cas_; - LocalAC<kDoGlobalUplink> ac_; - ::TargetCache<kDoGlobalUplink> tc_; + std::shared_ptr<CAS_t const> cas_; + std::shared_ptr<AC_t const> ac_; + std::shared_ptr<TC_t const> tc_; }; #ifdef BOOTSTRAP_BUILD_TOOL @@ -110,7 +111,9 @@ class Storage : public LocalStorage<kDefaultDoGlobalUplink> { using LocalStorage<kDefaultDoGlobalUplink>::LocalStorage; [[nodiscard]] static auto CreateStorage() noexcept -> Storage { - return Storage{StorageConfig::Instance().GenerationCacheDir(0)}; + auto gen_config = StorageConfig::Instance().CreateGenerationConfig( + Storage::kYoungest); + return Storage{gen_config}; } [[nodiscard]] static auto CreateGenerations() noexcept @@ -119,8 +122,9 @@ class Storage : public LocalStorage<kDefaultDoGlobalUplink> { std::vector<::Generation> generations{}; generations.reserve(count); for (std::size_t i = 0; i < count; ++i) { - generations.emplace_back( - StorageConfig::Instance().GenerationCacheDir(i)); + auto gen_config = + StorageConfig::Instance().CreateGenerationConfig(i); + generations.emplace_back(gen_config); } return generations; } diff --git a/src/buildtool/storage/target_cache.hpp b/src/buildtool/storage/target_cache.hpp index 2458b727..787a26b3 100644 --- a/src/buildtool/storage/target_cache.hpp +++ b/src/buildtool/storage/target_cache.hpp @@ -31,6 +31,7 @@ #include "src/buildtool/file_system/file_storage.hpp" #include "src/buildtool/file_system/object_type.hpp" #include "src/buildtool/logging/logger.hpp" +#include "src/buildtool/storage/config.hpp" #include "src/buildtool/storage/local_cas.hpp" #include "src/buildtool/storage/target_cache_entry.hpp" #include "src/buildtool/storage/target_cache_key.hpp" @@ -51,15 +52,16 @@ class TargetCache { using ArtifactDownloader = std::function<bool(std::vector<Artifact::ObjectInfo> const&)>; - explicit TargetCache(std::shared_ptr<LocalCAS<kDoGlobalUplink>> cas, - std::filesystem::path const& store_path) - : cas_{std::move(cas)}, - file_store_{store_path / ComputeShard()}, + explicit TargetCache( + gsl::not_null<LocalCAS<kDoGlobalUplink> const*> const& cas, + GenerationConfig const& config) + : cas_{*cas}, + file_store_{config.target_cache / ComputeShard()}, explicit_shard_{std::nullopt} { if constexpr (kDoGlobalUplink) { // write backend description (shard) to CAS [[maybe_unused]] auto id = - cas_->StoreBlob(RemoteExecutionConfig::DescribeBackend()); + cas_.StoreBlob(RemoteExecutionConfig::DescribeBackend()); EnsuresAudit(id and ArtifactDigest{*id}.hash() == ComputeShard()); } } @@ -126,7 +128,7 @@ class TargetCache { kDoGlobalUplink ? StoreMode::LastWins : StoreMode::FirstWins; std::shared_ptr<Logger> logger_{std::make_shared<Logger>("TargetCache")}; - gsl::not_null<std::shared_ptr<LocalCAS<kDoGlobalUplink>>> cas_; + LocalCAS<kDoGlobalUplink> const& cas_; FileStorage<ObjectType::File, kStoreMode, /*kSetEpochTime=*/false> diff --git a/src/buildtool/storage/target_cache.tpp b/src/buildtool/storage/target_cache.tpp index 7579d562..c2e89134 100644 --- a/src/buildtool/storage/target_cache.tpp +++ b/src/buildtool/storage/target_cache.tpp @@ -30,7 +30,7 @@ auto TargetCache<kDoGlobalUplink>::Store( if (not DownloadKnownArtifacts(value, downloader)) { return false; } - if (auto digest = cas_->StoreBlob(value.ToJson().dump(2))) { + if (auto digest = cas_.StoreBlob(value.ToJson().dump(2))) { auto data = Artifact::ObjectInfo{ArtifactDigest{*digest}, ObjectType::File} .ToString(); @@ -57,7 +57,7 @@ auto TargetCache<kDoGlobalUplink>::ComputeKey( nlohmann::json{target_name.module, target_name.name}.dump()}, {"effective_config", effective_config.ToString()}}; if (auto target_key = - cas_->StoreBlob(target_desc.dump(2), /*is_executable=*/false)) { + cas_.StoreBlob(target_desc.dump(2), /*is_executable=*/false)) { return TargetCacheKey{ {ArtifactDigest{*target_key}, ObjectType::File}}; } @@ -92,7 +92,7 @@ auto TargetCache<kDoGlobalUplink>::Read( return std::nullopt; } if (auto info = Artifact::ObjectInfo::FromString(*entry)) { - if (auto path = cas_->BlobPath(info->digest, /*is_executable=*/false)) { + if (auto path = cas_.BlobPath(info->digest, /*is_executable=*/false)) { if (auto value = FileSystemManager::ReadFile(*path)) { try { return std::make_pair( @@ -147,7 +147,7 @@ requires(kIsLocalGeneration) auto TargetCache<kDoGlobalUplink>:: // Determine target cache entry blob path of given generation. auto cache_entry = - cas_->BlobPath(entry_info->digest, /*is_executable=*/false); + cas_.BlobPath(entry_info->digest, /*is_executable=*/false); if (not cache_entry) { return false; } @@ -182,21 +182,20 @@ requires(kIsLocalGeneration) auto TargetCache<kDoGlobalUplink>:: // Uplink referenced artifacts. for (auto const& info : artifacts_info) { if (info.type == ObjectType::Tree) { - if (not cas_->LocalUplinkTree(*latest.cas_, info.digest)) { + if (not cas_.LocalUplinkTree(latest.cas_, info.digest)) { return false; } } - else if (not cas_->LocalUplinkBlob(*latest.cas_, - info.digest, - IsExecutableObject(info.type))) { + else if (not cas_.LocalUplinkBlob( + latest.cas_, info.digest, IsExecutableObject(info.type))) { return false; } } // Uplink target cache entry blob. - if (not cas_->LocalUplinkBlob(*latest.cas_, - entry_info->digest, - /*is_executable=*/false)) { + if (not cas_.LocalUplinkBlob(latest.cas_, + entry_info->digest, + /*is_executable=*/false)) { return false; } |