|  | // 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. | 
|  |  | 
|  | #ifndef SRC_TESTING_LOADBENCH_WORKLOAD_H_ | 
|  | #define SRC_TESTING_LOADBENCH_WORKLOAD_H_ | 
|  |  | 
|  | #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 = other.name; | 
|  | group = other.group; | 
|  | priority = other.priority; | 
|  | for (auto& action : other.actions) { | 
|  | actions.emplace_back(action->Copy()); | 
|  | } | 
|  | } | 
|  | 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 { | 
|  | public: | 
|  | 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_; } | 
|  |  | 
|  | private: | 
|  | 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_; | 
|  | }; | 
|  |  | 
|  | #endif  // SRC_TESTING_LOADBENCH_WORKLOAD_H_ |