blob: 59ab3d0d19294b5bb7a39d9a6aa31e24d21492d3 [file] [log] [blame]
// Copyright 2019 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 <lib/syslog/cpp/macros.h>
#include <lib/zx/time.h>
#include <optional>
#include <unordered_map>
#include <variant>
#include <vector>
#include "action.h"
#include "object.h"
#include "rapidjson/document.h"
struct WorkerConfig {
WorkerConfig() = default;
WorkerConfig(WorkerConfig&&) = default;
WorkerConfig& operator=(WorkerConfig&&) = default;
WorkerConfig(const WorkerConfig& other) { *this = other; }
WorkerConfig& operator=(const WorkerConfig& other) {
if (this != &other) {
name =;
group =;
priority = other.priority;
for (auto& action : other.actions) {
return *this;
struct DeadlineParams {
zx::duration capacity;
zx::duration deadline;
zx::duration period;
using PriorityType = std::variant<std::monostate, int, DeadlineParams>;
std::string name;
std::string group;
PriorityType priority;
std::vector<std::unique_ptr<Action>> actions;
struct TracingConfig {
uint32_t group_mask;
std::optional<std::string> filepath;
std::optional<std::string> trace_string_ref;
// Represents the configuration and state parsed from a workload JSON
// definition file.
class Workload {
static Workload Load(const std::string& path);
Workload() = default;
Workload(const Workload&) = delete;
Workload& operator=(const Workload&) = delete;
Workload(Workload&&) = default;
Workload& operator=(Workload&&) = default;
const auto& name() const { return name_; }
const auto& priority() const { return priority_; }
const auto& interval() const { return interval_; }
const auto& tracing() const { return tracing_; }
auto& workers() { return workers_; }
struct Duration {
std::chrono::nanoseconds value;
struct Uniform {
std::chrono::nanoseconds min;
std::chrono::nanoseconds max;
enum AcceptNamedIntervalFlag {
RejectNamedInterval = false,
AcceptNamedInterval = true,
void Add(const std::string& name, std::unique_ptr<Object> object) {
auto [iter, okay] = objects_.emplace(name, std::move(object));
FX_CHECK(okay) << "Object with name \"" << name << "\" defined more than once!";
Object& Get(const std::string& name) {
const auto search = objects_.find(name);
FX_CHECK(search != objects_.end()) << "name=" << name;
auto& [key, value] = *search;
return *value;
template <typename T>
T& Get(const std::string& name) {
const auto search = objects_.find(name);
FX_CHECK(search != objects_.end()) << "name=" << name;
auto& [key, value] = *search;
FX_CHECK(value->type() == T::Type) << "actual=" << value->type() << " expected=" << T::Type;
return static_cast<T&>(*value);
void ParseObject(const std::string& name, const rapidjson::Value& object);
Duration ParseDuration(const rapidjson::Value& object);
Uniform ParseUniform(const rapidjson::Value& object);
std::variant<Duration, Uniform> ParseInterval(const rapidjson::Value& object,
AcceptNamedIntervalFlag accept_named_interval);
void ParseNamedInterval(const std::string& name, const rapidjson::Value& object);
zx::unowned_handle ParseTargetObjectAndGetHandle(const std::string& name,
const rapidjson::Value& object,
const std::string& context);
std::unique_ptr<Action> ParseAction(const rapidjson::Value& action);
void ParseNamedBehavior(const std::string& name, const rapidjson::Value& behavior);
void ParseWorker(const rapidjson::Value& worker);
void ParseTracing(const rapidjson::Value& tracing);
std::string name_;
std::optional<int> priority_;
std::optional<std::chrono::nanoseconds> interval_;
std::unordered_map<std::string, std::variant<Duration, Uniform>> intervals_;
std::unordered_map<std::string, std::unique_ptr<Object>> objects_;
std::unordered_map<std::string, std::unique_ptr<Action>> behaviors_;
std::vector<WorkerConfig> workers_;
std::optional<TracingConfig> tracing_;