blob: ae2450cd4d0c9ebd0687094983bf5f4f8f846365 [file] [log] [blame]
Tyler Chatowa79419d2020-08-12 20:12:11 -07001#ifndef AOS_STARTER_STARTER_RPC_LIB_H_
2#define AOS_STARTER_STARTER_RPC_LIB_H_
3
4#include <chrono>
James Kuszmaul293b2172021-11-10 16:20:48 -08005#include <map>
milind upadhyaya87957a2021-03-06 20:46:30 -08006#include <optional>
James Kuszmaul293b2172021-11-10 16:20:48 -08007#include <vector>
Tyler Chatowa79419d2020-08-12 20:12:11 -07008
9#include "aos/configuration.h"
James Kuszmaul293b2172021-11-10 16:20:48 -080010#include "aos/events/event_loop.h"
Tyler Chatowa79419d2020-08-12 20:12:11 -070011#include "aos/starter/starter_generated.h"
12#include "aos/starter/starter_rpc_generated.h"
13
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -080014namespace aos::starter {
Tyler Chatowa79419d2020-08-12 20:12:11 -070015
James Kuszmaul293b2172021-11-10 16:20:48 -080016// Data required to command that starter start/stop/restart a given application.
17struct ApplicationCommand {
18 Command command;
19 std::string_view application;
20 std::vector<const aos::Node *> nodes;
21};
22
23// This class manages interacting with starterd so that you can conveniently
24// start/stop applications programmatically.
25// Note that the StarterClient only maintains internal state for a single set of
26// commands at once, so once the user calls SendCommands() they must wait for
27// the timeout or success handler to be called before calling SendCommands
28// again.
29class StarterClient {
30 public:
31 StarterClient(EventLoop *event_loop);
32
33 void SendCommands(const std::vector<ApplicationCommand> &commands,
34 monotonic_clock::duration timeout);
35
36 void SetTimeoutHandler(std::function<void()> handler) {
37 timeout_handler_ = handler;
38 }
39
40 void SetSuccessHandler(std::function<void()> handler) {
41 success_handler_ = handler;
42 }
43
44 private:
45 struct CommandStatus {
46 State expected_state;
47 std::string application;
48 std::optional<uint64_t> old_id;
49 };
50
51 bool CheckCommandsSucceeded();
52
53 void Timeout();
54
55 void Succeed();
56
57 EventLoop *event_loop_;
58 TimerHandler *timeout_timer_;
59 Sender<StarterRpc> cmd_sender_;
60 // Map of fetchers by node name.
61 std::map<std::string, Fetcher<Status>> status_fetchers_;
62
63 // Mapping of node name to a list of applications with pending commands.
64 std::map<std::string, std::vector<CommandStatus>> current_commands_;
65
66 std::function<void()> timeout_handler_;
67 std::function<void()> success_handler_;
68};
69
Tyler Chatowa79419d2020-08-12 20:12:11 -070070// Finds the status of an individual application within a starter status message
71// Returns nullptr if no application found by the given name.
72const aos::starter::ApplicationStatus *FindApplicationStatus(
73 const aos::starter::Status &status, std::string_view name);
74
milind upadhyay4272f382021-04-07 18:03:08 -070075// Checks if the name is an executable name and if it is, it returns that
76// application's name, otherwise returns name as given
Austin Schuhdae1e8d2022-03-26 15:09:31 -070077std::string_view FindApplication(const std::string_view name,
milind upadhyay4272f382021-04-07 18:03:08 -070078 const aos::Configuration *config);
79
Tyler Chatowa79419d2020-08-12 20:12:11 -070080// Sends the given command to the application with the name name. Creates a
81// temporary event loop from the provided config for sending the command and
82// receiving back status messages. Returns true if the command executed
83// successfully, or false otherwise. Returns false if the desired state was not
84// achieved within timeout.
85bool SendCommandBlocking(aos::starter::Command, std::string_view name,
86 const aos::Configuration *config,
James Kuszmaul293b2172021-11-10 16:20:48 -080087 std::chrono::milliseconds timeout,
88 std::vector<const aos::Node *> nodes = {});
Tyler Chatowa79419d2020-08-12 20:12:11 -070089
Austin Schuhe4b748a2021-10-16 14:19:58 -070090// Sends lots of commands and waits for them all to succeed. There must not be
91// more than 1 conflicting command in here which modifies the state of a single
92// application otherwise it will never succeed. An example is having both a
93// start and stop command for a single application.
James Kuszmaul293b2172021-11-10 16:20:48 -080094bool SendCommandBlocking(const std::vector<ApplicationCommand> &commands,
95 const aos::Configuration *config,
96 std::chrono::milliseconds timeout);
Austin Schuhe4b748a2021-10-16 14:19:58 -070097
Tyler Chatowa79419d2020-08-12 20:12:11 -070098// Fetches the status of the application with the given name. Creates a
James Kuszmaule4bb0a22022-01-07 18:14:43 -080099// temporary event loop from the provided config for fetching. Returns nullopt
100// if the application is not found.
James Kuszmaul2ca441b2022-01-07 18:16:23 -0800101// The returned pair is the time at which the ApplicationStatus was sent on the
102// node it was sent from, to allow calculating uptimes on remote nodes.
James Kuszmaule4bb0a22022-01-07 18:14:43 -0800103const std::optional<
James Kuszmaul2ca441b2022-01-07 18:16:23 -0800104 std::pair<aos::monotonic_clock::time_point,
105 aos::FlatbufferDetachedBuffer<aos::starter::ApplicationStatus>>>
James Kuszmaule4bb0a22022-01-07 18:14:43 -0800106GetStatus(std::string_view name, const aos::Configuration *config,
107 const aos::Node *node);
Tyler Chatowa79419d2020-08-12 20:12:11 -0700108
Philipp Schrader08537492021-01-23 16:17:55 -0800109// Fetches the entire status message of starter. Creates a temporary event loop
110// from the provided config for fetching.
James Kuszmaul293b2172021-11-10 16:20:48 -0800111// The returned pair is the time at which the Status was sent on the node it was
112// sent from, to allow calculating uptimes on remote nodes.
113// TODO(james): Use the ServerStatistics message and return the monotonic offset
114// instead, so that we can correctly handle high message latencies. Because
115// people don't generally care about ultra-high-precision uptime calculations,
116// this hasn't been prioritized.
117std::optional<std::pair<aos::monotonic_clock::time_point,
118 const aos::FlatbufferVector<aos::starter::Status>>>
119GetStarterStatus(const aos::Configuration *config, const aos::Node *node);
Philipp Schrader08537492021-01-23 16:17:55 -0800120
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -0800121} // namespace aos::starter
Tyler Chatowa79419d2020-08-12 20:12:11 -0700122
123#endif // AOS_STARTER_STARTER_RPC_LIB_H_