diff options
author | Oliver Reiche <oliver.reiche@huawei.com> | 2022-06-13 13:30:13 +0200 |
---|---|---|
committer | Oliver Reiche <oliver.reiche@huawei.com> | 2022-06-13 15:55:41 +0200 |
commit | a1c2e003f921cc4a04c5845ed18d75546a96fd88 (patch) | |
tree | 8c4682d797c0ede6bc2d156b931f6e3282fa68f4 /src/buildtool/build_engine/target_map/target_cache.cpp | |
parent | 27c3ec0bcab188a43c50ba4be0632ab8410bb677 (diff) | |
download | justbuild-a1c2e003f921cc4a04c5845ed18d75546a96fd88.tar.gz |
TargetCache: Initial implementation
Diffstat (limited to 'src/buildtool/build_engine/target_map/target_cache.cpp')
-rw-r--r-- | src/buildtool/build_engine/target_map/target_cache.cpp | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/src/buildtool/build_engine/target_map/target_cache.cpp b/src/buildtool/build_engine/target_map/target_cache.cpp new file mode 100644 index 00000000..aca14363 --- /dev/null +++ b/src/buildtool/build_engine/target_map/target_cache.cpp @@ -0,0 +1,115 @@ +#include "src/buildtool/build_engine/target_map/target_cache.hpp" + +#include "src/buildtool/common/repository_config.hpp" +#include "src/buildtool/execution_api/local/config.hpp" +#include "src/buildtool/execution_api/local/file_storage.hpp" +#include "src/buildtool/execution_api/local/local_cas.hpp" +#include "src/buildtool/execution_api/remote/config.hpp" +#include "src/buildtool/file_system/file_system_manager.hpp" +#include "src/buildtool/logging/logger.hpp" + +auto TargetCache::Key::Create(BuildMaps::Base::EntityName const& target, + Configuration const& effective_config) noexcept + -> std::optional<TargetCache::Key> { + static auto const& repos = RepositoryConfig::Instance(); + try { + if (auto repo_key = + repos.RepositoryKey(target.GetNamedTarget().repository)) { + // target's repository is content-fixed, we can compute a cache key + auto target_desc = nlohmann::json{ + {{"repo_key", *repo_key}, + {"target_name", target.ToString()}, + {"effective_config", effective_config.ToString()}}}; + static auto const& cas = LocalCAS<ObjectType::File>::Instance(); + if (auto target_key = cas.StoreBlobFromBytes(target_desc.dump(2))) { + return Key{ + {ArtifactDigest{std::move(*target_key)}, ObjectType::File}}; + } + } + } catch (std::exception const& ex) { + Logger::Log(LogLevel::Error, + "Creating target cache key failed with:\n{}", + ex.what()); + } + return std::nullopt; +} + +auto TargetCache::Entry::FromTarget( + AnalysedTargetPtr const& target, + std::unordered_map<ArtifactDescription, Artifact::ObjectInfo> const& + replacements) noexcept -> std::optional<TargetCache::Entry> { + auto result = TargetResult{ + target->Artifacts(), target->Provides(), target->RunFiles()}; + if (auto desc = result.ReplaceNonKnownAndToJson(replacements)) { + return Entry{*desc}; + } + return std::nullopt; +} + +auto TargetCache::Entry::ToResult() const -> std::optional<TargetResult> { + return TargetResult::FromJson(desc_); +} + +auto TargetCache::Store(Key const& key, Entry const& value) const noexcept + -> bool { + if (auto digest = CAS().StoreBlobFromBytes(value.ToJson().dump(2))) { + auto data = Artifact::ObjectInfo{ArtifactDigest{std::move(*digest)}, + ObjectType::File} + .ToString(); + logger_.Emit(LogLevel::Debug, + "Adding entry for key {} as {}", + key.Id().ToString(), + data); + return file_store_.AddFromBytes(key.Id().digest.hash(), data); + } + return false; +} + +auto TargetCache::Read(Key const& key) const noexcept + -> std::optional<std::pair<Entry, Artifact::ObjectInfo>> { + auto entry_path = file_store_.GetPath(key.Id().digest.hash()); + auto const entry = + FileSystemManager::ReadFile(entry_path, ObjectType::File); + if (not entry.has_value()) { + logger_.Emit(LogLevel::Debug, + "Cache miss, entry not found {}", + entry_path.string()); + return std::nullopt; + } + if (auto info = Artifact::ObjectInfo::FromString(*entry)) { + if (auto path = CAS().BlobPath(info->digest)) { + if (auto value = FileSystemManager::ReadFile(*path)) { + try { + return std::make_pair(Entry{nlohmann::json::parse(*value)}, + std::move(*info)); + } catch (std::exception const& ex) { + logger_.Emit(LogLevel::Warning, + "Parsing entry for key {} failed with:\n{}", + key.Id().ToString(), + ex.what()); + } + } + } + } + logger_.Emit(LogLevel::Warning, + "Reading entry for key {} failed", + key.Id().ToString()); + return std::nullopt; +} + +auto TargetCache::ComputeCacheDir() -> std::filesystem::path { + return LocalExecutionConfig::TargetCacheDir() / ExecutionBackendId(); +} + +auto TargetCache::ExecutionBackendId() -> std::string { + auto address = RemoteExecutionConfig::RemoteAddress(); + auto properties = RemoteExecutionConfig::PlatformProperties(); + auto backend_desc = nlohmann::json{ + {"remote_address", + address ? nlohmann::json{fmt::format( + "{}:{}", address->host, address->port)} + : nlohmann::json{}}, + {"platform_properties", + properties}}.dump(2); + return CAS().StoreBlobFromBytes(backend_desc).value().hash(); +} |