| #ifndef AOS_CONFIGURATION_H_ |
| #define AOS_CONFIGURATION_H_ |
| |
| #include <arpa/inet.h> |
| #include <netinet/in.h> |
| #include <sys/socket.h> |
| |
| #include <chrono> |
| #include <cstdint> |
| #include <string_view> |
| |
| #include "aos/configuration_generated.h" // IWYU pragma: export |
| #include "aos/flatbuffers.h" |
| |
| namespace aos { |
| |
| // Holds global configuration data. All of the functions are safe to call |
| // from wherever. |
| namespace configuration { |
| |
| // Reads a json configuration. This includes all imports and merges. Note: |
| // duplicate imports or invalid paths will result in a FATAL. |
| FlatbufferDetachedBuffer<Configuration> ReadConfig( |
| const std::string_view path, |
| const std::vector<std::string_view> &extra_import_paths = {}); |
| |
| // Reads a json configuration. This includes all imports and merges. Returns |
| // std::nullopt on duplicate imports or invalid paths. |
| std::optional<FlatbufferDetachedBuffer<Configuration>> MaybeReadConfig( |
| const std::string_view path, |
| const std::vector<std::string_view> &extra_import_paths = {}); |
| |
| // Sorts and merges entries in a config. |
| FlatbufferDetachedBuffer<Configuration> MergeConfiguration( |
| const Flatbuffer<Configuration> &config); |
| |
| // Adds schema definitions to a sorted and merged config from the provided |
| // schema list. |
| FlatbufferDetachedBuffer<Configuration> MergeConfiguration( |
| const Flatbuffer<Configuration> &config, |
| const std::vector<aos::FlatbufferVector<reflection::Schema>> &schemas); |
| |
| // Merges a configuration json snippet into the provided configuration and |
| // returns the modified config. |
| FlatbufferDetachedBuffer<Configuration> MergeWithConfig( |
| const Configuration *config, std::string_view json); |
| FlatbufferDetachedBuffer<Configuration> MergeWithConfig( |
| const Configuration *config, const Flatbuffer<Configuration> &addition); |
| |
| // Adds the list of schemas to the provide aos_config.json. This should mostly |
| // be used for testing and in conjunction with MergeWithConfig. |
| FlatbufferDetachedBuffer<aos::Configuration> AddSchema( |
| std::string_view json, |
| const std::vector<FlatbufferVector<reflection::Schema>> &schemas); |
| |
| // Returns the resolved Channel for a name, type, and application name. Returns |
| // nullptr if none is found. |
| // |
| // If the application name is empty, it is ignored. Maps are processed in |
| // reverse order, and application specific first. |
| // |
| // The config should already be fully merged and sorted (as produced by |
| // MergeConfiguration() or any of the associated functions). |
| const Channel *GetChannel(const Configuration *config, |
| const std::string_view name, |
| const std::string_view type, |
| const std::string_view application_name, |
| const Node *node, bool quiet = false); |
| inline const Channel *GetChannel(const Flatbuffer<Configuration> &config, |
| const std::string_view name, |
| const std::string_view type, |
| const std::string_view application_name, |
| const Node *node) { |
| return GetChannel(&config.message(), name, type, application_name, node); |
| } |
| template <typename T> |
| inline const Channel *GetChannel(const Configuration *config, |
| const std::string_view name, |
| const std::string_view application_name, |
| const Node *node) { |
| return GetChannel(config, name, T::GetFullyQualifiedName(), application_name, |
| node); |
| } |
| // Convenience wrapper for getting a channel from a specified config if you |
| // already have the name/type in a Channel object--this is useful if you Channel |
| // object you have does not point to memory within config. |
| inline const Channel *GetChannel(const Configuration *config, |
| const Channel *channel, |
| const std::string_view application_name, |
| const Node *node) { |
| return GetChannel(config, channel->name()->string_view(), |
| channel->type()->string_view(), application_name, node); |
| } |
| |
| // Returns a list of all the channel names that can be used to refer to the |
| // specified channel on the given node/application. this allows a reverse-lookup |
| // of any renames that happen. |
| // Does not perform forwards-lookup first. |
| std::set<std::string> GetChannelAliases(const Configuration *config, |
| std::string_view name, |
| std::string_view type, |
| const std::string_view application_name, |
| const Node *node); |
| inline std::set<std::string> GetChannelAliases( |
| const Configuration *config, const Channel *channel, |
| const std::string_view application_name, const Node *node) { |
| return GetChannelAliases(config, channel->name()->string_view(), |
| channel->type()->string_view(), application_name, |
| node); |
| } |
| |
| // Returns the channel index (or dies) of channel in the provided config. |
| size_t ChannelIndex(const Configuration *config, const Channel *channel); |
| |
| // Returns the Node out of the config with the matching name, or nullptr if it |
| // can't be found. |
| const Node *GetNode(const Configuration *config, std::string_view name); |
| const Node *GetNode(const Configuration *config, const Node *node); |
| // Returns the node with the provided index. This works in both a single and |
| // multi-node world. |
| const Node *GetNode(const Configuration *config, size_t node_index); |
| // Returns a matching node, or nullptr if the provided node is nullptr and we |
| // are in a single node world. |
| const Node *GetNodeOrDie(const Configuration *config, const Node *node); |
| // Returns the Node out of the configuration which matches our hostname. |
| // CHECKs if it can't be found. |
| const Node *GetMyNode(const Configuration *config); |
| const Node *GetNodeFromHostname(const Configuration *config, |
| std::string_view name); |
| |
| // Returns a vector of the nodes in the config. (nullptr is considered the node |
| // in a single node world.) |
| std::vector<const Node *> GetNodes(const Configuration *config); |
| |
| // Returns a vector of the nodes in the config with the provided tag. If this |
| // is a single-node world, we assume that all tags match. |
| std::vector<const Node *> GetNodesWithTag(const Configuration *config, |
| std::string_view tag); |
| |
| // Returns whether the given node has the provided tag. If this is a single-node |
| // world, we assume that all tags match. |
| bool NodeHasTag(const Node *node, std::string_view tag); |
| |
| // Returns the node index for a node. Note: will be faster if node is a pointer |
| // to a node in config, but is not required. |
| int GetNodeIndex(const Configuration *config, const Node *node); |
| int GetNodeIndex(const Configuration *config, std::string_view name); |
| // Returns the number of nodes. |
| size_t NodesCount(const Configuration *config); |
| |
| // Returns true if we are running in a multinode configuration. |
| bool MultiNode(const Configuration *config); |
| |
| // Returns true if the provided channel is sendable on the provided node. |
| bool ChannelIsSendableOnNode(const Channel *channel, const Node *node); |
| // Returns true if the provided channel is able to be watched or fetched on the |
| // provided node. |
| bool ChannelIsReadableOnNode(const Channel *channel, const Node *node); |
| |
| // Returns true if the provided channel is sent on the provided node and gets |
| // forwarded to any other nodes. |
| bool ChannelIsForwardedFromNode(const Channel *channel, const Node *node); |
| |
| // Returns true if the message is supposed to be logged on this node. |
| bool ChannelMessageIsLoggedOnNode(const Channel *channel, const Node *node); |
| bool ChannelMessageIsLoggedOnNode(const Channel *channel, |
| std::string_view node_name); |
| |
| // Returns the number of connections. |
| size_t ConnectionCount(const Channel *channel); |
| |
| const Connection *ConnectionToNode(const Channel *channel, const Node *node); |
| // Returns true if the delivery timestamps are supposed to be logged on this |
| // node. |
| bool ConnectionDeliveryTimeIsLoggedOnNode(const Channel *channel, |
| const Node *node, |
| const Node *logger_node); |
| bool ConnectionDeliveryTimeIsLoggedOnNode(const Connection *connection, |
| const Node *node); |
| |
| // Prints a channel to json, but without the schema. |
| std::string CleanedChannelToString(const Channel *channel); |
| // Prints out a channel to json, but only with the name and type. |
| std::string StrippedChannelToString(const Channel *channel); |
| |
| // Returns the node names that this node should be forwarding to. |
| std::vector<std::string_view> DestinationNodeNames(const Configuration *config, |
| const Node *my_node); |
| |
| // Returns the node names that this node should be receiving messages from. |
| std::vector<std::string_view> SourceNodeNames(const Configuration *config, |
| const Node *my_node); |
| |
| // Returns the source node index for each channel in a config. |
| std::vector<size_t> SourceNodeIndex(const Configuration *config); |
| |
| // Returns the all nodes that are logging timestamps on our node. |
| std::vector<const Node *> TimestampNodes(const Configuration *config, |
| const Node *my_node); |
| |
| // Returns the application for the provided node and name if it exists, or |
| // nullptr if it does not exist on this node. |
| const Application *GetApplication(const Configuration *config, |
| const Node *my_node, |
| std::string_view application_name); |
| |
| // Returns true if the provided application should start on the provided node. |
| bool ApplicationShouldStart(const Configuration *config, const Node *my_node, |
| const Application *application); |
| |
| // Returns the number of messages in the queue. |
| size_t QueueSize(const Configuration *config, const Channel *channel); |
| size_t QueueSize(size_t frequency, |
| std::chrono::nanoseconds channel_storage_duration); |
| |
| // Returns the number of scratch buffers in the queue. |
| int QueueScratchBufferSize(const Channel *channel); |
| |
| // Searches through configurations for schemas that include a certain type. |
| const reflection::Schema *GetSchema(const Configuration *config, |
| std::string_view schema_type); |
| |
| // GetSchema template |
| template <typename T> |
| const reflection::Schema *GetSchema(const Configuration *config) { |
| return GetSchema(config, T::GetFullyQualifiedName()); |
| } |
| |
| // Copy schema reflection into detached flatbuffer |
| std::optional<FlatbufferDetachedBuffer<reflection::Schema>> |
| GetSchemaDetachedBuffer(const Configuration *config, |
| std::string_view schema_type); |
| |
| // Returns the storage duration for a channel. |
| std::chrono::nanoseconds ChannelStorageDuration(const Configuration *config, |
| const Channel *channel); |
| |
| // Adds the specified channel to the config and returns the new, merged, config. |
| // The channel name is derived from the specified name, the type and schema from |
| // the provided schema, the source node from the specified node, and all other |
| // fields (e.g., frequency) will be derived from the overrides parameter. |
| aos::FlatbufferDetachedBuffer<Configuration> AddChannelToConfiguration( |
| const Configuration *config, std::string_view name, |
| aos::FlatbufferVector<reflection::Schema> schema, |
| const aos::Node *source_node = nullptr, ChannelT overrides = {}); |
| |
| } // namespace configuration |
| |
| // Compare and equality operators for Channel. Note: these only check the name |
| // and type for equality. |
| bool operator<(const FlatbufferDetachedBuffer<Channel> &lhs, |
| const FlatbufferDetachedBuffer<Channel> &rhs); |
| bool operator==(const FlatbufferDetachedBuffer<Channel> &lhs, |
| const FlatbufferDetachedBuffer<Channel> &rhs); |
| |
| } // namespace aos |
| |
| #endif // AOS_CONFIGURATION_H_ |