blob: 67b3fb20c4f56080a19a7a67a7d3bd5c6966f60f [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
milind upadhyay4272f382021-04-07 18:03:08 -070029std::string_view FindApplication(const std::string_view &name,
30 const aos::Configuration *config) {
31 std::string_view app_name = name;
32 for (const auto app : *config->applications()) {
33 if (app->executable_name() != nullptr &&
34 app->executable_name()->string_view() == name) {
35 app_name = app->name()->string_view();
36 break;
37 }
38 }
39 return app_name;
40}
41
Tyler Chatowa79419d2020-08-12 20:12:11 -070042bool SendCommandBlocking(aos::starter::Command command, std::string_view name,
43 const aos::Configuration *config,
44 std::chrono::milliseconds timeout) {
45 aos::ShmEventLoop event_loop(config);
46 event_loop.SkipAosLog();
47
48 ::aos::Sender<aos::starter::StarterRpc> cmd_sender =
49 event_loop.MakeSender<aos::starter::StarterRpc>("/aos");
50
51 // Wait until event loop starts to send command so watcher is ready
52 event_loop.OnRun([&cmd_sender, command, name] {
53 aos::Sender<aos::starter::StarterRpc>::Builder builder =
54 cmd_sender.MakeBuilder();
55
56 auto name_str = builder.fbb()->CreateString(name);
57
58 aos::starter::StarterRpc::Builder cmd_builder =
59 builder.MakeBuilder<aos::starter::StarterRpc>();
60
61 cmd_builder.add_name(name_str);
62 cmd_builder.add_command(command);
63
64 builder.Send(cmd_builder.Finish());
65 });
66
67 // If still waiting after timeout milliseconds, exit the loop
68 event_loop.AddTimer([&event_loop] { event_loop.Exit(); })
69 ->Setup(event_loop.monotonic_now() + timeout);
70
71 // Fetch the last list of statuses to compare the requested application's id
72 // against for commands such as restart.
73 auto initial_status_fetcher =
74 event_loop.MakeFetcher<aos::starter::Status>("/aos");
75 initial_status_fetcher.Fetch();
76 auto initial_status =
77 initial_status_fetcher
78 ? FindApplicationStatus(*initial_status_fetcher, name)
79 : nullptr;
80
81 const std::optional<uint64_t> initial_id =
82 (initial_status != nullptr && initial_status->has_id())
83 ? std::make_optional(initial_status->id())
84 : std::nullopt;
85
86 bool success = false;
87 event_loop.MakeWatcher(
88 "/aos", [&event_loop, command, name, initial_id,
89 &success](const aos::starter::Status &status) {
90 const aos::starter::ApplicationStatus *app_status =
91 FindApplicationStatus(status, name);
92
93 const std::optional<aos::starter::State> state =
94 (app_status != nullptr && app_status->has_state())
95 ? std::make_optional(app_status->state())
96 : std::nullopt;
97
98 switch (command) {
99 case aos::starter::Command::START: {
100 if (state == aos::starter::State::RUNNING) {
101 success = true;
102 event_loop.Exit();
103 }
104 break;
105 }
106 case aos::starter::Command::STOP: {
107 if (state == aos::starter::State::STOPPED) {
108 success = true;
109 event_loop.Exit();
110 }
111 break;
112 }
113 case aos::starter::Command::RESTART: {
114 if (state == aos::starter::State::RUNNING && app_status->has_id() &&
115 app_status->id() != initial_id) {
116 success = true;
117 event_loop.Exit();
118 }
119 break;
120 }
121 }
122 });
123
124 event_loop.Run();
125
126 return success;
127}
128
129const FlatbufferDetachedBuffer<aos::starter::ApplicationStatus> GetStatus(
130 std::string_view name, const Configuration *config) {
131 ShmEventLoop event_loop(config);
132 event_loop.SkipAosLog();
133
134 auto status_fetcher = event_loop.MakeFetcher<aos::starter::Status>("/aos");
135 status_fetcher.Fetch();
136 auto status =
137 status_fetcher ? FindApplicationStatus(*status_fetcher, name) : nullptr;
138 return status ? aos::CopyFlatBuffer(status)
139 : FlatbufferDetachedBuffer<
140 aos::starter::ApplicationStatus>::Empty();
141}
142
milind upadhyay4272f382021-04-07 18:03:08 -0700143std::optional<const aos::FlatbufferVector<aos::starter::Status>>
144GetStarterStatus(const aos::Configuration *config) {
Philipp Schrader08537492021-01-23 16:17:55 -0800145 ShmEventLoop event_loop(config);
146 event_loop.SkipAosLog();
147
148 auto status_fetcher = event_loop.MakeFetcher<aos::starter::Status>("/aos");
149 status_fetcher.Fetch();
milind upadhyay4272f382021-04-07 18:03:08 -0700150 return (status_fetcher ? std::make_optional(status_fetcher.CopyFlatBuffer())
151 : std::nullopt);
Philipp Schrader08537492021-01-23 16:17:55 -0800152}
153
Tyler Chatowa79419d2020-08-12 20:12:11 -0700154} // namespace starter
155} // namespace aos