blob: 5908abe7a6253de3ad32afad06a1d1a2b94de2c2 [file] [log] [blame]
James Kuszmaul9a816a72023-03-23 15:10:34 -07001#include "aos/starter/mock_starter.h"
2
3namespace aos {
4namespace starter {
5
6MockStarter::MockStarter(aos::EventLoop *event_loop)
7 : event_loop_(event_loop),
8 status_sender_(event_loop_->MakeSender<aos::starter::Status>("/aos")) {
9 aos::TimerHandler *send_timer =
10 event_loop_->AddTimer([this]() { SendStatus(); });
11
12 CHECK(aos::configuration::MultiNode(event_loop_->configuration()));
13
14 for (const aos::Node *node :
15 aos::configuration::GetNodes(event_loop_->configuration())) {
16 const aos::Channel *channel = aos::starter::StarterRpcChannelForNode(
17 event_loop_->configuration(), node);
18 if (aos::configuration::ChannelIsReadableOnNode(channel,
19 event_loop_->node())) {
20 std::string_view channel_name = channel->name()->string_view();
21 event_loop_->MakeWatcher(
22 channel_name, [this](const aos::starter::StarterRpc &command) {
23 for (const flatbuffers::String *node : *command.nodes()) {
24 if (node->string_view() ==
25 event_loop_->node()->name()->string_view()) {
26 CHECK(statuses_.count(command.name()->str()) > 0)
27 << "Unable to find " << command.name()->string_view()
28 << " in our list of applications.";
29 ApplicationStatus &status = statuses_[command.name()->str()];
30 switch (command.command()) {
31 case aos::starter::Command::START:
32 if (!status.running) {
33 status.running = true;
34 status.start_time = event_loop_->monotonic_now();
35 status.id = next_id_++;
36 }
37 break;
38 case aos::starter::Command::STOP:
39 status.running = false;
40 break;
41 case aos::starter::Command::RESTART:
42 status.running = true;
43 status.start_time = event_loop_->monotonic_now();
44 status.id = next_id_++;
45 }
46 SendStatus();
47 }
48 }
49 });
50 }
51 }
52
53 event_loop_->OnRun([this, send_timer]() {
54 send_timer->Setup(event_loop_->monotonic_now(), std::chrono::seconds(1));
55
56 for (const aos::Application *application :
57 *event_loop_->configuration()->applications()) {
58 if (aos::configuration::ApplicationShouldStart(
59 event_loop_->configuration(), event_loop_->node(), application)) {
60 statuses_[application->name()->str()] = ApplicationStatus{
61 next_id_++, application->autostart(), event_loop_->monotonic_now()};
62 }
63 }
64 });
65}
66
67void MockStarter::SendStatus() {
68 aos::Sender<aos::starter::Status>::Builder builder =
69 status_sender_.MakeBuilder();
70 std::vector<flatbuffers::Offset<aos::starter::ApplicationStatus>>
71 status_offsets;
72 for (const std::pair<const std::string, ApplicationStatus> &pair :
73 statuses_) {
74 const flatbuffers::Offset<flatbuffers::String> name_offset =
75 builder.fbb()->CreateString(pair.first);
76 aos::starter::ApplicationStatus::Builder status_builder =
77 builder.MakeBuilder<aos::starter::ApplicationStatus>();
78 status_builder.add_name(name_offset);
79 status_builder.add_state(pair.second.running
80 ? aos::starter::State::RUNNING
81 : aos::starter::State::STOPPED);
82 status_builder.add_last_exit_code(0);
83 status_builder.add_id(pair.second.id);
84 status_builder.add_last_stop_reason(
85 aos::starter::LastStopReason::STOP_REQUESTED);
86 status_builder.add_last_start_time(
87 pair.second.start_time.time_since_epoch().count());
88 if (pair.second.running) {
89 status_builder.add_pid(pair.second.id);
90 }
91 status_offsets.push_back(status_builder.Finish());
92 }
93 const flatbuffers::Offset<
94 flatbuffers::Vector<flatbuffers::Offset<aos::starter::ApplicationStatus>>>
95 statuses_offset = builder.fbb()->CreateVector(status_offsets);
96 aos::starter::Status::Builder status_builder =
97 builder.MakeBuilder<aos::starter::Status>();
98 status_builder.add_statuses(statuses_offset);
99 builder.CheckOk(builder.Send(status_builder.Finish()));
100}
101
102MockStarters::MockStarters(aos::SimulatedEventLoopFactory *event_loop_factory) {
103 CHECK(aos::configuration::MultiNode(event_loop_factory->configuration()));
104 for (const aos::Node *node :
105 aos::configuration::GetNodes(event_loop_factory->configuration())) {
106 event_loops_.emplace_back(
107 event_loop_factory->GetNodeEventLoopFactory(node)->MakeEventLoop(
108 "starterd"));
109 mock_starters_.emplace_back(
110 std::make_unique<MockStarter>(event_loops_.back().get()));
111 }
112}
113
114} // namespace starter
115} // namespace aos