Mads
Multi-Agent Distributed System
Loading...
Searching...
No Matches
agent.hpp
Go to the documentation of this file.
1/*
2 _ _ _
3 / \ __ _ ___ _ __ | |_ ___| | __ _ ___ ___
4 / _ \ / _` |/ _ \ '_ \| __| / __| |/ _` / __/ __|
5 / ___ \ (_| | __/ | | | |_ | (__| | (_| \__ \__ \
6 /_/ \_\__, |\___|_| |_|\__| \___|_|\__,_|___/___/
7 |___/
8
9Base class for all agents. This class is used to define the basic
10functionalities provided by all agents. Each agent subclass must implement the
11pure virtual functions defined in this class (currently none)
12
13Author(s): Paolo Bosetti
14*/
15
16#ifndef AGENT_HPP
17#define AGENT_HPP
18
19#if defined _WIN32 && !defined NOMINMAX
20#define NOMINMAX
21#endif
22
23#include "mads.hpp"
24#include <nlohmann/json.hpp>
25#ifdef _WIN32
26#include <winsock2.h>
27#else
28#include <unistd.h>
29#endif
30#ifndef _MSC_VER
31#pragma GCC diagnostic push
32#pragma GCC diagnostic ignored "-Wunknown-attributes"
33#endif
34#include <toml++/toml.hpp>
35#ifndef _MSC_VER
36#pragma GCC diagnostic pop
37#endif
38#include <iostream>
39#include <regex>
40#include <string>
41#include <string_view>
42#include <thread>
43#include <future>
44#include <zmq.hpp>
45#include <zmq_addon.hpp>
46#include <mutex>
47#include <condition_variable>
48#include <optional>
49#include <span>
50#include <atomic>
51#include <memory>
52#include "clock_offset.hpp"
53#include "curve.hpp"
54#include "exec_path.hpp"
55#include "socket_monitor.hpp"
56#include "topic_match.hpp"
57
58#ifndef HOST_NAME_MAX
59#define HOST_NAME_MAX 255
60#endif
61
62#ifndef MADS_AGENT_NO_INFO
63#include <rang.hpp>
64using namespace rang;
65#endif
66
67namespace Mads {
68
69template<typename T> struct SharedLatest {
70 std::mutex mtx;
71 std::condition_variable cv;
72 std::optional<T> value;
73};
74
88public:
89 LazyPayload() = default;
90 static LazyPayload from_text(std::string text) {
92 p._text = std::move(text);
93 return p;
94 }
95 static LazyPayload from_doc(nlohmann::json doc) {
97 p._doc = std::move(doc);
98 return p;
99 }
101 const std::string &text() const {
102 if (!_text)
103 _text = _doc ? _doc->dump() : std::string();
104 return *_text;
105 }
107 const nlohmann::json &doc() const {
108 if (!_doc) {
109 if (_text && !_text->empty())
110 _doc = nlohmann::json::parse(*_text);
111 else
112 _doc = nlohmann::json();
113 }
114 return *_doc;
115 }
116
117private:
118 mutable std::optional<std::string> _text;
119 mutable std::optional<nlohmann::json> _doc;
120};
121
140
141class Agent; // forward declaration
142
157std::unique_ptr<Agent> start_agent(std::string name, std::string settings_uri,
158 std::map<std::string, std::string> crypto_settings = {});
159
190class Agent {
191
192/*
193 ____ _ _ _
194 / ___|| |_ __ _| |_(_) ___
195 \___ \| __/ _` | __| |/ __|
196 ___) | || (_| | |_| | (__
197 |____/ \__\__,_|\__|_|\___|
198
199*/
200
201private:
210 void setup_curve_on(zmq::socket_t &socket);
211
230 std::tuple<std::string, std::string, double>
231 query_broker(std::string uri, std::string name,
232 int timeout = DEFAULT_SETTINGS_TIMEOUT_MS);
233
234public:
235/*
236 _ _ __ _
237 | | (_)/ _| ___ ___ _ _ ___| | ___
238 | | | | |_ / _ \/ __| | | |/ __| |/ _ \
239 | |___| | _| __/ (__| |_| | (__| | __/
240 |_____|_|_| \___|\___|\__, |\___|_|\___|
241 |___/
242*/
243
252 Agent(std::string name, std::string settings_uri);
253
254
271 void init(std::string name, std::string settings_uri, bool crypto = false, std::filesystem::path const &key_dir = "", bool install_watchdog = true);
272
273
283 void init(bool crypto = false, bool install_watchdog = true);
284
303 void fetch_settings(bool crypto = false);
304
305 // Destructor
306 virtual ~Agent();
307
315 void install_loop_watchdog(uint8_t max_count = 3);
316
317
318/*
319 ____ _ _ _
320 / ___| ___| |_| |_(_)_ __ __ _ ___
321 \___ \ / _ \ __| __| | '_ \ / _` / __|
322 ___) | __/ |_| |_| | | | | (_| \__ \
323 |____/ \___|\__|\__|_|_| |_|\__, |___/
324 |___/
325*/
326
334 virtual void load_settings();
335
336
343 void save_settings(const std::string path = SETTINGS_PATH);
344
345
350 nlohmann::json get_settings();
351
352
353#ifndef MADS_AGENT_NO_INFO
363 virtual void info(std::ostream &out = std::cout);
364#endif
365
366
367/*
368 ____ _ _
369 / ___|___ _ __ _ __ ___ ___| |_(_) ___ _ __
370 | | / _ \| '_ \| '_ \ / _ \/ __| __| |/ _ \| '_ \
371 | |__| (_) | | | | | | | __/ (__| |_| | (_) | | | |
372 \____\___/|_| |_|_| |_|\___|\___|\__|_|\___/|_| |_|
373
374*/
375
394 void connect(std::chrono::milliseconds delay = std::chrono::milliseconds(250));
395
412 bool wait_for_connection(std::chrono::milliseconds timeout);
413
433
438
439
447 void shutdown();
448
449
458 void set_cross(bool cross);
459
460
475 void enable_remote_control(bool threaded = false);
476
480
481
491 void register_event(const event_type event = event_type::marker,
492 const nlohmann::json &info = nlohmann::json(),
493 const std::string &info_name = "info");
494
495
502 void publish(nlohmann::json payload, std::string topic = "");
503
504
513 void publish(const char *payload, size_t len,
514 nlohmann::json meta = nlohmann::json{{"format", "raw"}},
515 std::string topic = "");
516
517
526 void publish(const std::vector<unsigned char> &payload,
527 nlohmann::json meta = nlohmann::json{{"format", "raw"}},
528 std::string topic = "");
529
530
541 message_type receive(bool dont_block = false);
542
569 bool receive_raw_message(std::string &topic, std::vector<std::string> &parts,
570 bool dont_block = false);
571
587 void publish_raw_message(const std::string &topic,
588 const std::vector<std::string> &parts);
589
590
591 /*
592 _
593 | | ___ ___ _ __
594 | | / _ \ / _ \| '_ \
595 | |__| (_) | (_) | |_) |
596 |_____\___/ \___/| .__/
597 |_|
598 */
599
626 using loop_fun_t = std::function<std::chrono::nanoseconds()>;
627 void loop(loop_fun_t const &lambda,
628 std::chrono::nanoseconds duration);
629
630
643 void loop(loop_fun_t const &lambda);
644
645
663 void enable_high_res_loop(bool on = true,
664 std::chrono::nanoseconds spin_margin =
665 std::chrono::microseconds(200));
666
670 bool high_res_loop() const;
671
672
680 void remote_control(std::string payload_str);
681
682
683 /*
684 _
685 / \ ___ ___ ___ ___ ___ ___ _ __ ___
686 / _ \ / __/ __/ _ \/ __/ __|/ _ \| '__/ __|
687 / ___ \ (_| (_| __/\__ \__ \ (_) | | \__ \
688 /_/ \_\___\___\___||___/___/\___/|_| |___/
689
690 */
691
697 void set_agent_id(std::string id);
698
699
700
706 std::string get_agent_id();
707
713 void set_sub_endpoint(std::string endpoint) { _sub_endpoint = endpoint; }
714
720 std::string sub_endpoint() const { return _sub_endpoint; }
721
727 void set_pub_endpoint(std::string endpoint) { _pub_endpoint = endpoint; }
728
734 std::string pub_endpoint() const { return _pub_endpoint; }
735
741 void set_pub_topic(std::string topic);
742
748 std::string pub_topic() const { return _pub_topic; }
749
755 void set_sub_topic(std::vector<std::string> topics) { _sub_topic = topics; }
756
762 std::vector<std::string> sub_topic() const { return _sub_topic; }
763
764
770 std::map<std::string, std::string> status();
771
772
778 std::string name();
779
780
787 std::tuple<std::string, std::string> last_message();
788
789
800 std::tuple<std::string, nlohmann::json> last_json();
801
802
808 std::string last_topic();
809
810
817 std::tuple<std::string, std::string, std::vector<unsigned char>> last_blob();
818
819
830 std::tuple<std::string_view, std::string_view,
831 std::span<const unsigned char>>
833
834
841 size_t dropped_messages() const;
842
843
849 bool settings_are_local() const;
850
851
858
859
866
867
876
884 void set_settings_timeout(std::chrono::milliseconds to);
885
886
893
894
903
911 void set_receive_timeout(std::chrono::milliseconds to);
912
913
919 bool restart();
920
931 std::shared_ptr<Mads::Runtime> runtime() const { return _runtime; }
932
942 bool running() const { return keep_running(); }
943
954 void set_runtime(std::shared_ptr<Mads::Runtime> runtime);
955
956
965 std::filesystem::path attachment_path();
966
967
973 bool is_crypto();
974
975
982
983
989 std::unique_ptr<CurveAuth> *curve_auth();
990
991
997 std::filesystem::path key_dir();
998
999
1005 void set_key_dir(const std::filesystem::path &path);
1006
1007 std::string settings_uri();
1008
1009
1010 [[deprecated("conflate is disabled; use set_delivery(Delivery::LastKnownValue)")]]
1012 [[deprecated("conflate is disabled; use delivery()")]]
1013 bool conflate();
1014
1024 void set_high_watermark(int i = 1000);
1026
1034 void set_delivery(Delivery d);
1035
1039 Delivery delivery() const;
1040
1050 void set_wire_format(WireFormat fmt);
1051
1055 WireFormat wire_format() const;
1056
1066 void set_compression(Compression c);
1067
1071 Compression compression() const;
1072
1081
1082
1083 /*
1084 ____ _ _ ___ __ __ _
1085 / ___| | ___ ___| | __ / _ \ / _|/ _|___ ___| |_
1086 | | | |/ _ \ / __| |/ /| | | | |_| |_/ __|/ _ \ __|
1087 | |___| | (_) | (__| < | |_| | _| _\__ \ __/ |_
1088 \____|_|\___/ \___|_|\_\ \___/|_| |_| |___/\___|\__|
1089
1090 */
1091
1110 int timeout_ms = 1000);
1111
1129 std::vector<Mads::ClockPeerObservation> broadcast_clock_probe(
1130 std::chrono::milliseconds window = std::chrono::milliseconds(300));
1131
1140
1147 std::string clock_domain() const;
1148
1149 double timecode_fps = MADS_FPS;
1151 std::string server_key_name = "broker";
1152 std::string client_key_name = "client";
1153
1154 /*
1155 ____ _ _
1156 | _ \ _ __(_)_ ____ _| |_ ___
1157 | |_) | '__| \ \ / / _` | __/ _ \
1158 | __/| | | |\ V / (_| | || __/
1159 |_| |_| |_| \_/ \__,_|\__\___|
1160
1161 */
1162
1163protected:
1170 bool keep_running() const {
1171 return _runtime->running() && !_stopping.load();
1172 }
1173
1179 void connect_pub(std::chrono::milliseconds delay = std::chrono::milliseconds(0));
1180
1181
1187
1188
1197 bool receive_raw(zmq::multipart_t &message, bool dont_block = false);
1198
1209 bool _topic_matches_subscription(const std::string &topic) const;
1210
1211 static std::tuple<std::string, std::string, std::string> split_URL(const std::string &url);
1212
1222
1230
1237
1241 bool _clock_wants_sync() const;
1242
1254
1260
1265 void _handle_clocksync_message(const nlohmann::json &msg);
1266
1270
1276 uint8_t hops);
1277
1282 std::string _clock_agent_identity() const;
1283
1284 // Member variables
1285 std::string _hostname;
1286 std::string _name;
1287 std::string _settings_uri;
1288 std::string _raw_settings;
1289 toml::table _config;
1291 std::string _pub_topic;
1292 std::string _agent_id;
1293 std::vector<std::string> _sub_topic;
1294 // Subset of _sub_topic containing a '+'/'#' wildcard token (P2), computed
1295 // once by connect_sub(). Empty for every agent using only literal
1296 // sub_topic entries, which keeps the receive-time filter a single cheap
1297 // emptiness check in that -- the common -- case, adding no overhead.
1298 std::vector<std::string> _wildcard_sub_topic;
1299 zmq::context_t _context;
1300 zmq::socket_t _publisher;
1301 zmq::socket_t _subscriber;
1302 // Attached before each socket's connect()/bind() (ZMQ_DEVELOPMENT.md
1303 // §2.1); stopped in shutdown() before the sockets are closed.
1306 // A single LazyPayload per message is shared between _last_message and
1307 // _status so the lazy text/object caches are shared and never duplicated.
1308 std::map<std::string, std::shared_ptr<LazyPayload>> _status;
1309 std::tuple<std::string, std::shared_ptr<LazyPayload>> _last_message;
1310 std::tuple<std::string, std::string, std::vector<unsigned char>> _last_blob;
1311 mutable std::mutex _message_state_mutex;
1312 bool _cross = false;
1313 bool _connected = false;
1314 int _receive_timeout = DEFAULT_RECEIVE_TIMEOUT_MS;
1316 bool _init_done = false;
1317 bool _settings_fetched = false;
1318 bool _restart = false;
1319 std::shared_ptr<Mads::Runtime> _runtime = std::make_shared<Mads::Runtime>();
1320 // Per-agent stop request: set by shutdown()/disconnect(), cleared by
1321 // connect(). Keeps an individual agent's teardown from stopping the other
1322 // agents that share its Runtime.
1323 std::atomic<bool> _stopping{false};
1325 std::chrono::nanoseconds _time_step = std::chrono::nanoseconds(0);
1326 bool _high_res_loop = false;
1327 std::chrono::nanoseconds _spin_margin = std::chrono::microseconds(200);
1328 double _timecode_offset = 0.0;
1329 std::filesystem::path _attachment_path;
1330 bool _crypto = false;
1331 bool _conflate = false;
1332 std::unique_ptr<CurveAuth> _curve_auth = nullptr;
1333 std::filesystem::path _key_dir;
1334 bool _last_value_only = false;
1335 bool _shutdown_done = false;
1337 // The agent's one socket thread (ZMQ_DEVELOPMENT.md §4.1). It always polls
1338 // both socket monitors' PAIR sockets -- which used to cost a thread each --
1339 // and additionally owns _subscriber exclusively whenever LKV delivery
1340 // and/or threaded remote control need it consumed off the application
1341 // thread. A single thread rather than one per feature: two threads calling
1342 // recv() on the same (non-thread-safe) ZMQ socket is undefined behaviour,
1343 // and with LKV and threaded remote control both enabled it also meant a
1344 // message landed on whichever thread's recv() call won the race.
1345 std::thread _io_thread;
1346 // Whether _io_thread polls _subscriber at all. Set by connect_sub() only
1347 // once the socket is fully subscribed, and read by _io_thread, so it must
1348 // be atomic even though it never changes after that.
1349 std::atomic<bool> _io_reads_subscriber{false};
1350 std::thread _watchdog_thread;
1351 // Delayed startup-event publisher: owned (not detached) so shutdown() can
1352 // wake it via _event_cv and join it before the sockets close.
1354 std::mutex _event_mtx;
1355 std::condition_variable _event_cv;
1356 // ZMQ sockets are not thread-safe; the event thread publishes concurrently
1357 // with the owner thread, so sends on _publisher are serialized.
1358 std::mutex _publish_mutex;
1359 std::atomic<bool> _watchdog_stop{false};
1360 bool _rc_owns_socket = false;
1361 WireFormat _wire_format = WireFormat::Json;
1362 Compression _compression = Compression::Auto;
1363 std::atomic<size_t> _dropped_messages{0};
1364 nlohmann::json _settings_json; // cached JSON projection of settings
1365
1366 // ---- Clock offset (see clock_offset.hpp) --------------------------
1371 bool _clock_correction = false;
1372 // Per-clock-domain adoption (§2 of the design): every agent, regardless
1373 // of its own clock_source, records what it hears so clock_offset() can
1374 // return the domain's winner rather than only this agent's own
1375 // measurement.
1376 Mads::ClockConsensus _clock_consensus{std::chrono::seconds(30)};
1377 // This agent's own last measurement (source Broker or Peer), guarded
1378 // separately from _clock_consensus's own internal mutex since it is
1379 // read/written by measure_clock_offset()/_run_peer_measurement() (the
1380 // clock thread or init()) and read by clock_offset() (any thread).
1381 mutable std::mutex _clock_mtx;
1383 uint64_t _clock_seq = 0;
1384 std::thread _clock_thread;
1385 // Pending broadcast_clock_probe() collection state: the send instant (for
1386 // local_elapsed_us) and the pongs gathered so far. Single-flight by
1387 // design (see broadcast_clock_probe()'s doc comment).
1388 mutable std::mutex _clocksync_mtx;
1389 std::chrono::steady_clock::time_point _clocksync_probe_sent_at{};
1390 std::vector<Mads::ClockPeerObservation> _clocksync_pongs;
1392 // Per-initiator rate limit for this agent's own ping responses (§4.1 of
1393 // the design): guarded by _clocksync_mtx too.
1394 std::map<std::string, std::chrono::steady_clock::time_point>
1396
1397public:
1398 bool dummy = false;
1399};
1400
1401} // namespace Mads
1402
1403#endif // AGENT_HPP
void set_wire_format(WireFormat fmt)
Select the on-the-wire payload encoding used when publishing.
bool restart()
Returns wheter a restart has been requested.
std::mutex _publish_mutex
Definition agent.hpp:1358
toml::table _config
Definition agent.hpp:1289
std::thread _watchdog_thread
Definition agent.hpp:1350
std::string name()
Returns the name of the agent.
std::mutex _clocksync_mtx
Definition agent.hpp:1388
virtual ~Agent()
bool _clock_correction
Definition agent.hpp:1371
Mads::LinkState link_state() const
The current state of this agent's link to the broker: up or down, why (last_handshake – e....
std::map< std::string, std::chrono::steady_clock::time_point > _clocksync_last_reply
Definition agent.hpp:1395
std::filesystem::path attachment_path()
Returns the path to the attachment file.
Mads::ClockOffsetResult clock_offset() const
This agent's currently adopted clock offset: the clock domain's consensus winner (Mads::ClockConsensu...
void set_compression(Compression c)
Select the payload compression policy for outgoing messages.
bool _init_done
Definition agent.hpp:1316
uint64_t _clock_seq
Definition agent.hpp:1383
std::string _pub_endpoint
Definition agent.hpp:1290
void enable_threaded_remote_control()
Definition agent.hpp:477
void shutdown()
Performs a coordinated shutdown of the agent.
int _clock_interval_ms
Definition agent.hpp:1369
void _announce_clock_offset(const Mads::ClockOffsetResult &r)
void set_sub_topic(std::vector< std::string > topics)
Sets the subscribe topics.
Definition agent.hpp:755
std::thread _startup_event_thread
Definition agent.hpp:1353
std::string pub_endpoint() const
Get the publish endpoint URL.
Definition agent.hpp:734
std::filesystem::path _attachment_path
Definition agent.hpp:1329
std::string clock_domain() const
This process's clock-domain identity (Mads::detail::clock_domain_id(): boot_id on Linux,...
std::vector< std::string > sub_topic() const
Gets the subscribe topics.
Definition agent.hpp:762
std::string get_agent_id()
Get the agent ID.
void init(bool crypto=false, bool install_watchdog=true)
Initializes the agent.
Mads::ClockOffsetResult measure_clock_offset(size_t samples=5, int timeout_ms=1000)
Runs samples four-timestamp exchanges against the broker's settings endpoint and adopts the result as...
bool is_crypto()
Returns whether CURVE encryption is enabled.
Agent(std::string name, std::string settings_uri)
Constructs an Agent object with the given name and settings path. If the settings path is a URI,...
Mads::SocketMonitor _sub_monitor
Definition agent.hpp:1305
std::string _raw_settings
Definition agent.hpp:1288
void loop(loop_fun_t const &lambda)
Enters the main loop of the agent. It also sets a signal handler for SIGNINT, which will set the runn...
bool conflate()
double _timecode_offset
Definition agent.hpp:1328
std::string _name
Definition agent.hpp:1286
void set_pub_endpoint(std::string endpoint)
Set the publish endpoint URL.
Definition agent.hpp:727
std::string client_key_name
Definition agent.hpp:1152
std::string settings_uri()
std::atomic< size_t > _dropped_messages
Definition agent.hpp:1363
std::vector< std::string > _sub_topic
Definition agent.hpp:1293
bool _clock_sync_responder
Definition agent.hpp:1368
void set_runtime(std::shared_ptr< Mads::Runtime > runtime)
Attach the agent to a different Runtime.
void connect(std::chrono::milliseconds delay=std::chrono::milliseconds(250))
Connects the agent to the publish and subscribe endpoints.
Mads::ClockOffsetResult _own_clock_measurement
Definition agent.hpp:1382
bool _crypto
Definition agent.hpp:1330
void set_receive_timeout(std::chrono::milliseconds to)
Sets the value of timeout in receiving messages. Set to 0 for no timeout.
bool _shutdown_done
Definition agent.hpp:1335
int high_watermark()
void set_delivery(Delivery d)
Select subscriber delivery semantics.
std::filesystem::path key_dir()
Returns the path to the etc directory.
std::tuple< std::string, nlohmann::json > last_json()
Returns the last received message as a parsed JSON object.
std::condition_variable _event_cv
Definition agent.hpp:1355
std::chrono::nanoseconds _spin_margin
Definition agent.hpp:1327
void save_settings(const std::string path=SETTINGS_PATH)
Save settings read from broker to file.
int _receive_timeout
Definition agent.hpp:1314
void publish(const std::vector< unsigned char > &payload, nlohmann::json meta=nlohmann::json{{"format", "raw"}}, std::string topic="")
Publishes a message with the given binary blob payload.
std::unique_ptr< CurveAuth > * curve_auth()
Returns a pointer to the CurveAuth object.
void publish_raw_message(const std::string &topic, const std::vector< std::string > &parts)
Publishes a raw multi-part message with no JSON encoding, no automatic field-stamping (agent_id/hostn...
bool _clock_wants_sync() const
void init(std::string name, std::string settings_uri, bool crypto=false, std::filesystem::path const &key_dir="", bool install_watchdog=true)
Initializes the agent.
std::tuple< std::string_view, std::string_view, std::span< const unsigned char > > last_blob_view() const
Zero-copy view of the last received blob.
bool receive_raw(zmq::multipart_t &message, bool dont_block=false)
Internal use wrapping the receive step both for normal operations and for LastKnown Value (LKV) seman...
SharedLatest< zmq::multipart_t > _latest_message
Definition agent.hpp:1336
void set_settings_timeout(std::chrono::milliseconds to)
Sets the value of timeout in loading settings from URI. Set to for no timeout.
bool _connected
Definition agent.hpp:1313
bool _topic_matches_subscription(const std::string &topic) const
MQTT-style wildcard filter (P2): true if topic is accepted by at least one entry of _sub_topic – lite...
Mads::ClockOffsetResult _stamp_clock_result(Mads::ClockOffsetResult r, Mads::ClockSource source, uint8_t hops)
std::thread _io_thread
Definition agent.hpp:1345
std::vector< Mads::ClockPeerObservation > broadcast_clock_probe(std::chrono::milliseconds window=std::chrono::milliseconds(300))
Broadcasts a clock-sync ping on CLOCKSYNC_TOPIC and collects every responder's pong that arrives with...
void set_pub_topic(std::string topic)
Sets the publish topic.
void enable_remote_control(bool threaded=false)
Enables remote control for the agent.
bool _conflate
Definition agent.hpp:1331
bool wait_for_connection(std::chrono::milliseconds timeout)
Blocks until the publisher socket's connection is confirmed by a real ZMQ_EVENT_CONNECTED/ZMQ_EVENT_H...
virtual void info(std::ostream &out=std::cout)
Prints information about the agent.
void set_cross(bool cross)
Sets the cross flag.
size_t dropped_messages() const
Number of messages dropped because they were malformed or could not be decoded (bad part count,...
bool _high_res_loop
Definition agent.hpp:1326
std::function< std::chrono::nanoseconds()> loop_fun_t
Enters the main loop of the agent. It also sets a signal handler for SIGNINT, which will set the runn...
Definition agent.hpp:626
std::mutex _clock_mtx
Definition agent.hpp:1381
void remote_control(std::string payload_str)
Handles remote control commands.
int receive_timeout()
Returns the value of timeout in receiving messages.
Mads::SocketMonitor _pub_monitor
Definition agent.hpp:1304
std::vector< Mads::ClockPeerObservation > _clocksync_pongs
Definition agent.hpp:1390
std::string _settings_uri
Definition agent.hpp:1287
std::atomic< bool > _watchdog_stop
Definition agent.hpp:1359
std::atomic< bool > _io_reads_subscriber
Definition agent.hpp:1349
void set_conflate(bool conflate)
void enable_high_res_loop(bool on=true, std::chrono::nanoseconds spin_margin=std::chrono::microseconds(200))
Opt into (or out of) high-resolution loop pacing.
nlohmann::json _settings_json
Definition agent.hpp:1364
void _handle_clocksync_message(const nlohmann::json &msg)
static void install_signal_handlers()
Install SIGINT/SIGTERM handlers that request a clean shutdown.
std::string _hostname
Definition agent.hpp:1285
std::map< std::string, std::string > status()
Returns the status of the system.
uint64_t _clocksync_probe_seq
Definition agent.hpp:1391
void set_high_watermark(int i=1000)
Set the high watermark (ZMQ receive queue bound).
zmq::socket_t _subscriber
Definition agent.hpp:1301
void publish(const char *payload, size_t len, nlohmann::json meta=nlohmann::json{{"format", "raw"}}, std::string topic="")
Publishes a message with the given binary blob payload.
bool is_connected()
Detects if agent is connected.
void loop(loop_fun_t const &lambda, std::chrono::nanoseconds duration)
std::shared_ptr< Mads::Runtime > _runtime
Definition agent.hpp:1319
std::tuple< std::string, std::shared_ptr< LazyPayload > > _last_message
Definition agent.hpp:1309
void set_agent_id(std::string id)
Set the agent ID field.
std::string sub_endpoint() const
Get the subscribe endpoint URL.
Definition agent.hpp:720
std::string _pub_topic
Definition agent.hpp:1291
void _configure_clock_sync()
Parses the [agents]/[<name>] clock_* settings during init() and appends CLOCKSYNC_TOPIC to _sub_topic...
int _clock_announce_ms
Definition agent.hpp:1370
WireFormat _wire_format
Definition agent.hpp:1361
message_type receive(bool dont_block=false)
Receives a message from the subscribe socket.
Mads::ClockSource _clock_source
Definition agent.hpp:1367
double timecode_fps
Definition agent.hpp:1149
void _run_peer_measurement()
std::mutex _message_state_mutex
Definition agent.hpp:1311
std::chrono::nanoseconds _time_step
Definition agent.hpp:1325
void _start_clock_thread()
Brings up _clock_thread if it is not already running: announces this agent's adopted clock offset on ...
bool high_res_loop() const
Returns whether high-resolution loop pacing is enabled.
std::filesystem::path _key_dir
Definition agent.hpp:1333
std::mutex _event_mtx
Definition agent.hpp:1354
bool _settings_fetched
Definition agent.hpp:1317
nlohmann::json get_settings()
Get all settings as JSON.
bool running() const
True while this agent's loops should keep going.
Definition agent.hpp:942
static std::tuple< std::string, std::string, std::string > split_URL(const std::string &url)
int settings_timeout()
Returns the value of timeout in loading settings from URI.
bool settings_are_local() const
Detects if settings are local or loaded from URI.
void fetch_settings(bool crypto=false)
Acquires settings (and any broker-served attachment) without binding the agent to a settings section.
void _start_io_thread()
Brings up _io_thread if it is not already running. Called from whichever of connect_pub()/connect_sub...
std::string pub_topic() const
Gets the publish topic.
Definition agent.hpp:748
bool keep_running() const
True while this agent's loops should keep going.
Definition agent.hpp:1170
void install_loop_watchdog(uint8_t max_count=3)
Install a watch thread to ensure exit from loops.
void set_sub_endpoint(std::string endpoint)
Set the subscribe endpoint URL.
Definition agent.hpp:713
void set_settings_timeout(int to)
Sets the value of timeout in loading settings from URI. Set to for no timeout.
zmq::socket_t _publisher
Definition agent.hpp:1300
std::tuple< std::string, std::string, std::vector< unsigned char > > last_blob()
Returns the last received blob by the agent.
std::shared_ptr< Mads::Runtime > runtime() const
The Runtime that owns this agent's run state.
Definition agent.hpp:931
Delivery delivery() const
Current delivery semantics.
bool _cross
Definition agent.hpp:1312
void _apply_socket_options()
Resolves the plain libzmq transport-tuning knobs (ZMQ_DEVELOPMENT.md §1.4: TCP keepalive,...
std::map< std::string, std::shared_ptr< LazyPayload > > _status
Definition agent.hpp:1308
std::atomic< bool > _stopping
Definition agent.hpp:1323
void setup_crypto(Mads::auth_verbose verbose=auth_verbose::off)
Set the use of CURVE encryption and enables authentication.
std::string server_key_name
Definition agent.hpp:1151
void set_key_dir(const std::filesystem::path &path)
Sets the path to the etc directory.
int _settings_timeout
Definition agent.hpp:1315
Compression compression() const
The compression policy used for outgoing messages.
std::tuple< std::string, std::string > last_message()
Returns the last received message by the agent.
void connect_pub(std::chrono::milliseconds delay=std::chrono::milliseconds(0))
Connects the agent to the publish endpoint.
void publish(nlohmann::json payload, std::string topic="")
Publishes a message with the given JSON payload.
zmq::context_t _context
Definition agent.hpp:1299
void register_event(const event_type event=event_type::marker, const nlohmann::json &info=nlohmann::json(), const std::string &info_name="info")
Registers an event.
WireFormat wire_format() const
The wire format used for outgoing messages.
Compression _compression
Definition agent.hpp:1362
bool _rc_owns_socket
Definition agent.hpp:1360
bool _remote_controlled
Definition agent.hpp:1324
bool receive_raw_message(std::string &topic, std::vector< std::string > &parts, bool dont_block=false)
Receives a message without any JSON/blob (de)serialization (P3).
std::thread _clock_thread
Definition agent.hpp:1384
std::vector< std::string > _wildcard_sub_topic
Definition agent.hpp:1298
virtual void load_settings()
Additional settings to be loaded. Virtual function to be implemented by the derived class.
void set_receive_timeout(int to)
Sets the value of timeout in receiving messages. Set to 0 for no timeout.
void connect_sub()
Connects the agent to the subscribe endpoint and subscribes to the topics.
Mads::ClockConsensus _clock_consensus
Definition agent.hpp:1376
std::string _clock_agent_identity() const
std::string _agent_id
Definition agent.hpp:1292
std::unique_ptr< CurveAuth > _curve_auth
Definition agent.hpp:1332
std::string _sub_endpoint
Definition agent.hpp:1290
std::chrono::steady_clock::time_point _clocksync_probe_sent_at
Definition agent.hpp:1389
std::tuple< std::string, std::string, std::vector< unsigned char > > _last_blob
Definition agent.hpp:1310
bool _restart
Definition agent.hpp:1318
std::string last_topic()
Returns the topic of the last received message by the agent.
bool _last_value_only
Definition agent.hpp:1334
void disconnect()
Disconnects the agent from the publish and subscribe endpoints.
Per-clock-domain adoption of the smallest-delay measurement heard from any agent sharing that domain ...
A received message payload that lazily holds either its JSON text or its parsed nlohmann::json form,...
Definition agent.hpp:87
static LazyPayload from_doc(nlohmann::json doc)
Definition agent.hpp:95
LazyPayload()=default
const nlohmann::json & doc() const
Parsed object form (parses the cached text once if only text exists).
Definition agent.hpp:107
const std::string & text() const
JSON text form (dumps the cached object once if only the object exists).
Definition agent.hpp:101
static LazyPayload from_text(std::string text)
Definition agent.hpp:90
One monitor per monitored socket. start() must be called before the socket's connect()/bind(): libzmq...
Definition agent.hpp:67
ClockSource
Which mechanism produced a ClockOffsetResult.
auth_verbose
Definition curve.hpp:35
std::unique_ptr< Agent > start_agent(std::string name, std::string settings_uri, std::map< std::string, std::string > crypto_settings={})
Quick Agent initialization function.
Result of a clock-offset measurement: offset_us added to a clock in the measured domain yields broker...
One responder's answer to Agent::broadcast_clock_probe()'s ping (clock-offset source B,...
Definition agent.hpp:130
std::string responder_domain
Definition agent.hpp:134
std::string responder_hostname
Definition agent.hpp:133
ClockOffsetResult responder_adopted
Definition agent.hpp:138
std::string responder_name
Definition agent.hpp:132
std::string responder_agent_id
Definition agent.hpp:131
One four-timestamp exchange, all fields microseconds since the Unix epoch: t1/t4 read from the initia...
std::mutex mtx
Definition agent.hpp:70
std::condition_variable cv
Definition agent.hpp:71
std::optional< T > value
Definition agent.hpp:72