blob: efb4042e3fc44b79dbfac658085053821c6c7545 [file] [log] [blame]
Tyler Chatowa79419d2020-08-12 20:12:11 -07001#include "starter_rpc_lib.h"
2
3#include "aos/events/shm_event_loop.h"
4#include "aos/flatbuffer_merge.h"
5
6namespace aos {
7namespace starter {
8
9const aos::starter::ApplicationStatus *FindApplicationStatus(
10 const aos::starter::Status &status, std::string_view name) {
11 if (!status.has_statuses()) {
12 return nullptr;
13 }
14
15 auto statuses = status.statuses();
16
17 auto search =
18 std::find_if(statuses->begin(), statuses->end(),
19 [name](const aos::starter::ApplicationStatus *app_status) {
20 return app_status->has_name() &&
21 app_status->name()->string_view() == name;
22 });
23 if (search == statuses->end()) {
24 return nullptr;
25 }
26 return *search;
27}
28
29bool SendCommandBlocking(aos::starter::Command command, std::string_view name,
30 const aos::Configuration *config,
31 std::chrono::milliseconds timeout) {
32 aos::ShmEventLoop event_loop(config);
33 event_loop.SkipAosLog();
34
35 ::aos::Sender<aos::starter::StarterRpc> cmd_sender =
36 event_loop.MakeSender<aos::starter::StarterRpc>("/aos");
37
38 // Wait until event loop starts to send command so watcher is ready
39 event_loop.OnRun([&cmd_sender, command, name] {
40 aos::Sender<aos::starter::StarterRpc>::Builder builder =
41 cmd_sender.MakeBuilder();
42
43 auto name_str = builder.fbb()->CreateString(name);
44
45 aos::starter::StarterRpc::Builder cmd_builder =
46 builder.MakeBuilder<aos::starter::StarterRpc>();
47
48 cmd_builder.add_name(name_str);
49 cmd_builder.add_command(command);
50
51 builder.Send(cmd_builder.Finish());
52 });
53
54 // If still waiting after timeout milliseconds, exit the loop
55 event_loop.AddTimer([&event_loop] { event_loop.Exit(); })
56 ->Setup(event_loop.monotonic_now() + timeout);
57
58 // Fetch the last list of statuses to compare the requested application's id
59 // against for commands such as restart.
60 auto initial_status_fetcher =
61 event_loop.MakeFetcher<aos::starter::Status>("/aos");
62 initial_status_fetcher.Fetch();
63 auto initial_status =
64 initial_status_fetcher
65 ? FindApplicationStatus(*initial_status_fetcher, name)
66 : nullptr;
67
68 const std::optional<uint64_t> initial_id =
69 (initial_status != nullptr && initial_status->has_id())
70 ? std::make_optional(initial_status->id())
71 : std::nullopt;
72
73 bool success = false;
74 event_loop.MakeWatcher(
75 "/aos", [&event_loop, command, name, initial_id,
76 &success](const aos::starter::Status &status) {
77 const aos::starter::ApplicationStatus *app_status =
78 FindApplicationStatus(status, name);
79
80 const std::optional<aos::starter::State> state =
81 (app_status != nullptr && app_status->has_state())
82 ? std::make_optional(app_status->state())
83 : std::nullopt;
84
85 switch (command) {
86 case aos::starter::Command::START: {
87 if (state == aos::starter::State::RUNNING) {
88 success = true;
89 event_loop.Exit();
90 }
91 break;
92 }
93 case aos::starter::Command::STOP: {
94 if (state == aos::starter::State::STOPPED) {
95 success = true;
96 event_loop.Exit();
97 }
98 break;
99 }
100 case aos::starter::Command::RESTART: {
101 if (state == aos::starter::State::RUNNING && app_status->has_id() &&
102 app_status->id() != initial_id) {
103 success = true;
104 event_loop.Exit();
105 }
106 break;
107 }
108 }
109 });
110
111 event_loop.Run();
112
113 return success;
114}
115
116const FlatbufferDetachedBuffer<aos::starter::ApplicationStatus> GetStatus(
117 std::string_view name, const Configuration *config) {
118 ShmEventLoop event_loop(config);
119 event_loop.SkipAosLog();
120
121 auto status_fetcher = event_loop.MakeFetcher<aos::starter::Status>("/aos");
122 status_fetcher.Fetch();
123 auto status =
124 status_fetcher ? FindApplicationStatus(*status_fetcher, name) : nullptr;
125 return status ? aos::CopyFlatBuffer(status)
126 : FlatbufferDetachedBuffer<
127 aos::starter::ApplicationStatus>::Empty();
128}
129
130} // namespace starter
131} // namespace aos