blob: 73452e84053d0747a41ad626464d1f5691ad7996 [file]
// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/devices/bin/driver_manager/composite/parent_set_collector.h"
#include <fidl/fuchsia.driver.framework/cpp/fidl.h>
#include "src/devices/lib/log/log.h"
namespace driver_manager {
zx::result<> ParentSetCollector::AddNode(
uint32_t index, const std::vector<fuchsia_driver_framework::NodeProperty2>& node_properties,
std::weak_ptr<Node> node) {
ZX_ASSERT(HasCompositeInfo());
ZX_ASSERT(index < parents_.size());
if (parents_[index] != std::nullopt && !parents_[index]->expired()) {
return zx::error(ZX_ERR_ALREADY_BOUND);
}
parents_[index] = std::move(node);
parent_properties_[index] =
fuchsia_driver_framework::NodePropertyEntry2(parent_names_.value()[index], node_properties);
if (auto node_ptr = parents_[index]->lock(); node_ptr) {
node_ptr->MarkAsCompositeParent();
}
return zx::ok();
}
void ParentSetCollector::ReleaseNodes() {
for (auto& node : parents_) {
if (node == std::nullopt) {
continue;
}
if (auto node_ptr = node->lock(); node_ptr) {
node_ptr->UnmarkAsCompositeParent();
}
node.reset();
}
}
zx::result<std::shared_ptr<Node>> ParentSetCollector::TryToAssemble(
std::string_view name, NodeManager* node_manager, async_dispatcher_t* dispatcher) {
ZX_ASSERT(HasCompositeInfo());
if (completed_composite_node_ && !completed_composite_node_->expired()) {
return zx::error(ZX_ERR_ALREADY_EXISTS);
}
std::vector<NodeWkPtr> parent_nodes;
parent_nodes.reserve(parents_.size());
for (auto& node : parents_) {
if (node == std::nullopt) {
return zx::error(ZX_ERR_SHOULD_WAIT);
}
parent_nodes.emplace_back(node.value());
}
auto result = Node::CreateCompositeNode(std::string(name), parent_nodes, parent_names_.value(),
parent_properties_, node_manager, dispatcher,
driver_host_name_for_colocation_, primary_index_.value());
if (result.is_error()) {
return result.take_error();
}
fdf_log::info("Built composite node '{}' for completed composite node spec", name);
completed_composite_node_.emplace(result.value());
return zx::ok(result.value());
}
fuchsia_driver_development::wire::CompositeNodeInfo ParentSetCollector::GetCompositeInfo(
fidl::AnyArena& arena,
const std::optional<fuchsia_driver_framework::CompositeInfo>& composite_info) const {
namespace fdd = fuchsia_driver_development;
auto composite_node_info = fdd::wire::CompositeNodeInfo::Builder(arena);
if (composite_info.has_value()) {
composite_node_info.composite(fdd::wire::CompositeInfo::WithComposite(
arena, fidl::ToWire(arena, composite_info.value())));
}
if (!HasCompositeInfo()) {
fidl::VectorView<fidl::StringView> parent_topological_paths(arena, size());
composite_node_info.parent_topological_paths(parent_topological_paths);
composite_node_info.parent_monikers(fidl::VectorView<fidl::StringView>(arena, size()));
return composite_node_info.Build();
}
composite_node_info.parent_topological_paths(GetParentTopologicalPaths(arena));
composite_node_info.parent_monikers(GetParentMonikers(arena));
std::optional<NodeWkPtr> composite_node = completed_composite_node();
if (composite_node) {
if (auto node_ptr = composite_node->lock(); node_ptr) {
composite_node_info.topological_path(node_ptr->MakeTopologicalPath());
composite_node_info.moniker(fidl::StringView(arena, node_ptr->MakeComponentMoniker()));
}
}
return composite_node_info.Build();
}
fidl::VectorView<fidl::StringView> ParentSetCollector::GetParentTopologicalPaths(
fidl::AnyArena& arena) const {
fidl::VectorView<fidl::StringView> parent_topological_paths(arena, parents_.size());
for (uint32_t i = 0; i < parents_.size(); i++) {
if (parents_[i] == std::nullopt) {
parent_topological_paths[i] = fidl::StringView();
continue;
}
if (auto node = parents_[i]->lock(); node) {
parent_topological_paths[i] = fidl::StringView(arena, node->MakeTopologicalPath());
} else {
parent_topological_paths[i] = fidl::StringView();
}
}
return parent_topological_paths;
}
fidl::VectorView<fidl::StringView> ParentSetCollector::GetParentMonikers(
fidl::AnyArena& arena) const {
fidl::VectorView<fidl::StringView> parent_monikers(arena, parents_.size());
for (uint32_t i = 0; i < parents_.size(); i++) {
if (parents_[i] == std::nullopt) {
parent_monikers[i] = fidl::StringView();
continue;
}
if (auto node = parents_[i]->lock(); node) {
parent_monikers[i] = fidl::StringView(arena, node->MakeComponentMoniker());
} else {
parent_monikers[i] = fidl::StringView();
}
}
return parent_monikers;
}
} // namespace driver_manager