blob: f75c258d629d9418a0911b89af5d23efe889a3fe [file] [log] [blame]
// Copyright 2018 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "runtime_probe/component_category.h"
#include <memory>
#include <utility>
#include <base/barrier_callback.h>
#include <base/functional/bind.h>
#include <base/functional/callback.h>
#include <base/logging.h>
#include <base/values.h>
#include <brillo/map_utils.h>
#include "runtime_probe/probe_statement.h"
namespace runtime_probe {
namespace {
// Callback to handle a single result from |ProbeStatement::EvalAsync|.
void OnProbeStatementEvalCompleted(
base::OnceCallback<void(base::Value::List)> callback,
const std::string& component_name,
std::optional<base::Value> information_dv,
base::Value::List probe_result) {
base::Value::List results;
for (auto& probe_statement_dv : probe_result) {
base::Value::Dict result;
result.Set("name", component_name);
result.Set("values", std::move(probe_statement_dv));
if (information_dv.has_value())
result.Set("information", information_dv->Clone());
results.Append(std::move(result));
}
std::move(callback).Run(std::move(results));
}
void CollectProbeStatementResults(
base::OnceCallback<void(base::Value::List)> callback,
std::vector<base::Value::List> probe_results) {
base::Value::List results;
for (auto& probe_result : probe_results) {
for (auto& result : probe_result) {
results.Append(std::move(result));
}
}
std::move(callback).Run(std::move(results));
}
} // namespace
std::unique_ptr<ComponentCategory> ComponentCategory::FromValue(
const std::string& category_name, const base::Value& dv) {
if (!dv.is_dict()) {
LOG(ERROR) << "ComponentCategory::FromValue takes a dictionary as"
<< " parameter";
return nullptr;
}
std::unique_ptr<ComponentCategory> instance{new ComponentCategory()};
instance->category_name_ = category_name;
for (const auto& entry : dv.GetDict()) {
const auto& component_name = entry.first;
const auto& value = entry.second;
auto probe_statement = ProbeStatement::FromValue(component_name, value);
if (!probe_statement) {
LOG(ERROR) << "Component " << component_name
<< " doesn't contain a valid probe statement.";
return nullptr;
}
instance->component_[component_name] = std::move(probe_statement);
}
return instance;
}
void ComponentCategory::Eval(
base::OnceCallback<void(base::Value::List)> callback) const {
auto barrier_callback = base::BarrierCallback<base::Value::List>(
component_.size(),
base::BindOnce(&CollectProbeStatementResults, std::move(callback)));
for (auto& [component_name, probe_statement] : component_)
probe_statement->Eval(base::BindOnce(&OnProbeStatementEvalCompleted,
barrier_callback, component_name,
probe_statement->GetInformation()));
}
std::vector<std::string> ComponentCategory::GetComponentNames() const {
return brillo::GetMapKeysAsVector(component_);
}
} // namespace runtime_probe