// Copyright 2022 Huawei Cloud Computing Technology Co., Ltd. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "src/buildtool/execution_engine/dag/dag.hpp" auto DependencyGraph::CreateOutputArtifactNodes( std::string const& action_id, std::vector const& file_paths, std::vector const& dir_paths, bool is_tree_action) -> std::pair, std::vector> { if (is_tree_action) { // create tree artifact auto artifact = ArtifactDescription::CreateTree(action_id).ToArtifact(); auto const node_id = AddArtifact(std::move(artifact)); return std::make_pair(std::vector{}, std::vector{ {{}, &(*artifact_nodes_[node_id])}}); } // create action artifacts auto node_creator = [this, &action_id](auto* nodes, auto const& paths) { for (auto const& artifact_path : paths) { auto artifact = ArtifactDescription::CreateAction( action_id, std::filesystem::path{artifact_path}) .ToArtifact(); auto const node_id = AddArtifact(std::move(artifact)); nodes->emplace_back(NamedArtifactNodePtr{ artifact_path, &(*artifact_nodes_[node_id])}); } }; std::vector file_nodes{}; file_nodes.reserve(file_paths.size()); node_creator(&file_nodes, file_paths); std::vector dir_nodes{}; dir_nodes.reserve(dir_paths.size()); node_creator(&dir_nodes, dir_paths); return std::make_pair(std::move(file_nodes), std::move(dir_nodes)); } auto DependencyGraph::CreateInputArtifactNodes( ActionDescription::inputs_t const& inputs) -> std::optional> { std::vector nodes{}; for (auto const& [local_path, artifact_desc] : inputs) { auto artifact = artifact_desc.ToArtifact(); auto const node_id = AddArtifact(std::move(artifact)); nodes.push_back({local_path, &(*artifact_nodes_[node_id])}); } return nodes; } auto DependencyGraph::CreateActionNode(Action const& action) noexcept -> DependencyGraph::ActionNode* { if (action.IsTreeAction() or not action.Command().empty()) { auto const node_id = AddAction(action); return &(*action_nodes_[node_id]); } return nullptr; } auto DependencyGraph::LinkNodePointers( std::vector const& output_files, std::vector const& output_dirs, gsl::not_null const& action_node, std::vector const& input_nodes) noexcept -> bool { for (auto const& named_file : output_files) { if (not named_file.node->AddBuilderActionNode(action_node) or not action_node->AddOutputFile(named_file)) { return false; } } for (auto const& named_dir : output_dirs) { if (not named_dir.node->AddBuilderActionNode(action_node) or not action_node->AddOutputDir(named_dir)) { return false; } } for (auto const& named_node : input_nodes) { if (not named_node.node->AddConsumerActionNode(action_node) or not action_node->AddDependency(named_node)) { return false; } } action_node->NotifyDoneLinking(); return true; } auto DependencyGraph::Add(std::vector const& actions) -> bool { return std::all_of( actions.begin(), actions.end(), [this](auto const& action) { return AddAction(action); }); } auto DependencyGraph::Add(std::vector const& actions) -> bool { return std::all_of( actions.begin(), actions.end(), [this](auto const& action) { return AddAction(*action); }); } auto DependencyGraph::AddArtifact(ArtifactDescription const& description) -> ArtifactIdentifier { auto artifact = description.ToArtifact(); auto id = artifact.Id(); [[maybe_unused]] auto const node_id = AddArtifact(std::move(artifact)); return id; } auto DependencyGraph::AddAction(ActionDescription const& description) -> bool { auto output_nodes = CreateOutputArtifactNodes(description.Id(), description.OutputFiles(), description.OutputDirs(), description.GraphAction().IsTreeAction()); auto* action_node = CreateActionNode(description.GraphAction()); auto input_nodes = CreateInputArtifactNodes(description.Inputs()); if (action_node == nullptr or not input_nodes.has_value() or (output_nodes.first.empty() and output_nodes.second.empty())) { return false; } return LinkNodePointers( output_nodes.first, output_nodes.second, action_node, *input_nodes); } auto DependencyGraph::AddAction(Action const& a) noexcept -> DependencyGraph::ActionNodeIdentifier { auto const& id = a.Id(); auto const action_it = action_ids_.find(id); if (action_it != action_ids_.end()) { return action_it->second; } action_nodes_.emplace_back(ActionNode::Create(a)); ActionNodeIdentifier node_id{action_nodes_.size() - 1}; action_ids_[id] = node_id; return node_id; } auto DependencyGraph::AddAction(Action&& a) noexcept -> DependencyGraph::ActionNodeIdentifier { auto const& id = a.Id(); auto const action_it = action_ids_.find(id); if (action_it != action_ids_.end()) { return action_it->second; } action_nodes_.emplace_back(ActionNode::Create(std::move(a))); ActionNodeIdentifier node_id{action_nodes_.size() - 1}; action_ids_[id] = node_id; return node_id; } auto DependencyGraph::AddArtifact(Artifact const& a) noexcept -> DependencyGraph::ArtifactNodeIdentifier { auto const& id = a.Id(); auto const artifact_it = artifact_ids_.find(id); if (artifact_it != artifact_ids_.end()) { return artifact_it->second; } artifact_nodes_.emplace_back(ArtifactNode::Create(a)); ArtifactNodeIdentifier node_id{artifact_nodes_.size() - 1}; artifact_ids_[id] = node_id; return node_id; } auto DependencyGraph::AddArtifact(Artifact&& a) noexcept -> DependencyGraph::ArtifactNodeIdentifier { auto id = a.Id(); auto const artifact_it = artifact_ids_.find(id); if (artifact_it != artifact_ids_.end()) { return artifact_it->second; } artifact_nodes_.emplace_back(ArtifactNode::Create(std::move(a))); ArtifactNodeIdentifier node_id{artifact_nodes_.size() - 1}; artifact_ids_[id] = node_id; return node_id; } auto DependencyGraph::ArtifactIdentifiers() const noexcept -> std::unordered_set { std::unordered_set ids; std::transform( std::begin(artifact_ids_), std::end(artifact_ids_), std::inserter(ids, std::begin(ids)), [](auto const& artifact_id_pair) { return artifact_id_pair.first; }); return ids; } auto DependencyGraph::ArtifactNodeWithId(ArtifactIdentifier const& id) const noexcept -> DependencyGraph::ArtifactNode const* { auto it_to_artifact = artifact_ids_.find(id); if (it_to_artifact == artifact_ids_.end()) { return nullptr; } return &(*artifact_nodes_[it_to_artifact->second]); } auto DependencyGraph::ActionNodeWithId(ActionIdentifier const& id) const noexcept -> DependencyGraph::ActionNode const* { auto it_to_action = action_ids_.find(id); if (it_to_action == action_ids_.end()) { return nullptr; } return &(*action_nodes_[it_to_action->second]); }