blob: a949928409fbead30fcf22d44ca0a313f09bb8bd [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
Austin Schuh0dcdf1d2024-03-27 12:55:41 -070040 // Sets the callback to be called on success. Note: this isn't safe to call
41 // while the previous success handler is running unless you use std::ref to
42 // manage its lifetime some other way.
James Kuszmaul293b2172021-11-10 16:20:48 -080043 void SetSuccessHandler(std::function<void()> handler) {
Austin Schuh0dcdf1d2024-03-27 12:55:41 -070044 success_handler_ = std::move(handler);
James Kuszmaul293b2172021-11-10 16:20:48 -080045 }
46
47 private:
48 struct CommandStatus {
49 State expected_state;
50 std::string application;
51 std::optional<uint64_t> old_id;
52 };
53
54 bool CheckCommandsSucceeded();
55
56 void Timeout();
57
58 void Succeed();
59
60 EventLoop *event_loop_;
61 TimerHandler *timeout_timer_;
62 Sender<StarterRpc> cmd_sender_;
63 // Map of fetchers by node name.
64 std::map<std::string, Fetcher<Status>> status_fetchers_;
65
66 // Mapping of node name to a list of applications with pending commands.
67 std::map<std::string, std::vector<CommandStatus>> current_commands_;
68
69 std::function<void()> timeout_handler_;
70 std::function<void()> success_handler_;
71};
72
Tyler Chatowa79419d2020-08-12 20:12:11 -070073// Finds the status of an individual application within a starter status message
74// Returns nullptr if no application found by the given name.
75const aos::starter::ApplicationStatus *FindApplicationStatus(
76 const aos::starter::Status &status, std::string_view name);
77
milind upadhyay4272f382021-04-07 18:03:08 -070078// Checks if the name is an executable name and if it is, it returns that
79// application's name, otherwise returns name as given
Austin Schuhdae1e8d2022-03-26 15:09:31 -070080std::string_view FindApplication(const std::string_view name,
milind upadhyay4272f382021-04-07 18:03:08 -070081 const aos::Configuration *config);
82
Tyler Chatowa79419d2020-08-12 20:12:11 -070083// Sends the given command to the application with the name name. Creates a
84// temporary event loop from the provided config for sending the command and
85// receiving back status messages. Returns true if the command executed
86// successfully, or false otherwise. Returns false if the desired state was not
87// achieved within timeout.
88bool SendCommandBlocking(aos::starter::Command, std::string_view name,
89 const aos::Configuration *config,
James Kuszmaul293b2172021-11-10 16:20:48 -080090 std::chrono::milliseconds timeout,
91 std::vector<const aos::Node *> nodes = {});
Tyler Chatowa79419d2020-08-12 20:12:11 -070092
Austin Schuhe4b748a2021-10-16 14:19:58 -070093// Sends lots of commands and waits for them all to succeed. There must not be
94// more than 1 conflicting command in here which modifies the state of a single
95// application otherwise it will never succeed. An example is having both a
96// start and stop command for a single application.
James Kuszmaul293b2172021-11-10 16:20:48 -080097bool SendCommandBlocking(const std::vector<ApplicationCommand> &commands,
98 const aos::Configuration *config,
99 std::chrono::milliseconds timeout);
Austin Schuhe4b748a2021-10-16 14:19:58 -0700100
Tyler Chatowa79419d2020-08-12 20:12:11 -0700101// Fetches the status of the application with the given name. Creates a
James Kuszmaule4bb0a22022-01-07 18:14:43 -0800102// temporary event loop from the provided config for fetching. Returns nullopt
103// if the application is not found.
James Kuszmaul2ca441b2022-01-07 18:16:23 -0800104// The returned pair is the time at which the ApplicationStatus was sent on the
105// node it was sent from, to allow calculating uptimes on remote nodes.
James Kuszmaule4bb0a22022-01-07 18:14:43 -0800106const std::optional<
James Kuszmaul2ca441b2022-01-07 18:16:23 -0800107 std::pair<aos::monotonic_clock::time_point,
108 aos::FlatbufferDetachedBuffer<aos::starter::ApplicationStatus>>>
James Kuszmaule4bb0a22022-01-07 18:14:43 -0800109GetStatus(std::string_view name, const aos::Configuration *config,
110 const aos::Node *node);
Tyler Chatowa79419d2020-08-12 20:12:11 -0700111
Philipp Schrader08537492021-01-23 16:17:55 -0800112// Fetches the entire status message of starter. Creates a temporary event loop
113// from the provided config for fetching.
James Kuszmaul293b2172021-11-10 16:20:48 -0800114// The returned pair is the time at which the Status was sent on the node it was
115// sent from, to allow calculating uptimes on remote nodes.
116// TODO(james): Use the ServerStatistics message and return the monotonic offset
117// instead, so that we can correctly handle high message latencies. Because
118// people don't generally care about ultra-high-precision uptime calculations,
119// this hasn't been prioritized.
120std::optional<std::pair<aos::monotonic_clock::time_point,
121 const aos::FlatbufferVector<aos::starter::Status>>>
122GetStarterStatus(const aos::Configuration *config, const aos::Node *node);
Philipp Schrader08537492021-01-23 16:17:55 -0800123
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -0800124} // namespace aos::starter
Tyler Chatowa79419d2020-08-12 20:12:11 -0700125
126#endif // AOS_STARTER_STARTER_RPC_LIB_H_