blob: 9f9a2b5a014b7343158c19e75e7c5cf123b82cb1 [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) {
James Kuszmaul75b09352023-02-03 16:21:25 -080033 VLOG(1) << "Starting " << command.name()->string_view()
34 << " at " << event_loop_->monotonic_now();
James Kuszmaul9a816a72023-03-23 15:10:34 -070035 status.running = true;
36 status.start_time = event_loop_->monotonic_now();
37 status.id = next_id_++;
38 }
39 break;
40 case aos::starter::Command::STOP:
James Kuszmaul75b09352023-02-03 16:21:25 -080041 if (status.running) {
42 VLOG(1) << "Stopping " << command.name()->string_view()
43 << " at " << event_loop_->monotonic_now();
44 }
James Kuszmaul9a816a72023-03-23 15:10:34 -070045 status.running = false;
46 break;
47 case aos::starter::Command::RESTART:
48 status.running = true;
James Kuszmaul75b09352023-02-03 16:21:25 -080049 VLOG(1) << "Restarting " << command.name()->string_view()
50 << " at " << event_loop_->monotonic_now();
James Kuszmaul9a816a72023-03-23 15:10:34 -070051 status.start_time = event_loop_->monotonic_now();
52 status.id = next_id_++;
53 }
54 SendStatus();
55 }
56 }
57 });
58 }
59 }
60
61 event_loop_->OnRun([this, send_timer]() {
Philipp Schradera6712522023-07-05 20:25:11 -070062 send_timer->Schedule(event_loop_->monotonic_now(), std::chrono::seconds(1));
James Kuszmaul9a816a72023-03-23 15:10:34 -070063
64 for (const aos::Application *application :
65 *event_loop_->configuration()->applications()) {
66 if (aos::configuration::ApplicationShouldStart(
67 event_loop_->configuration(), event_loop_->node(), application)) {
68 statuses_[application->name()->str()] = ApplicationStatus{
69 next_id_++, application->autostart(), event_loop_->monotonic_now()};
70 }
71 }
72 });
73}
74
75void MockStarter::SendStatus() {
76 aos::Sender<aos::starter::Status>::Builder builder =
77 status_sender_.MakeBuilder();
78 std::vector<flatbuffers::Offset<aos::starter::ApplicationStatus>>
79 status_offsets;
80 for (const std::pair<const std::string, ApplicationStatus> &pair :
81 statuses_) {
82 const flatbuffers::Offset<flatbuffers::String> name_offset =
83 builder.fbb()->CreateString(pair.first);
84 aos::starter::ApplicationStatus::Builder status_builder =
85 builder.MakeBuilder<aos::starter::ApplicationStatus>();
86 status_builder.add_name(name_offset);
87 status_builder.add_state(pair.second.running
88 ? aos::starter::State::RUNNING
89 : aos::starter::State::STOPPED);
90 status_builder.add_last_exit_code(0);
91 status_builder.add_id(pair.second.id);
92 status_builder.add_last_stop_reason(
93 aos::starter::LastStopReason::STOP_REQUESTED);
94 status_builder.add_last_start_time(
95 pair.second.start_time.time_since_epoch().count());
96 if (pair.second.running) {
97 status_builder.add_pid(pair.second.id);
98 }
99 status_offsets.push_back(status_builder.Finish());
100 }
101 const flatbuffers::Offset<
102 flatbuffers::Vector<flatbuffers::Offset<aos::starter::ApplicationStatus>>>
103 statuses_offset = builder.fbb()->CreateVector(status_offsets);
104 aos::starter::Status::Builder status_builder =
105 builder.MakeBuilder<aos::starter::Status>();
106 status_builder.add_statuses(statuses_offset);
107 builder.CheckOk(builder.Send(status_builder.Finish()));
108}
109
110MockStarters::MockStarters(aos::SimulatedEventLoopFactory *event_loop_factory) {
111 CHECK(aos::configuration::MultiNode(event_loop_factory->configuration()));
112 for (const aos::Node *node :
113 aos::configuration::GetNodes(event_loop_factory->configuration())) {
114 event_loops_.emplace_back(
115 event_loop_factory->GetNodeEventLoopFactory(node)->MakeEventLoop(
116 "starterd"));
117 mock_starters_.emplace_back(
118 std::make_unique<MockStarter>(event_loops_.back().get()));
119 }
120}
121
122} // namespace starter
123} // namespace aos