Commit 4cd321b1 authored by Dominik Charousset's avatar Dominik Charousset

Move to settings alias, change parse signature

Consequently use the new settings type alias and drop config_value_map
entirely. All parse functions in actor_system_config now take a settings
argument and return an error object.
parent 0541cbae
...@@ -99,6 +99,7 @@ set(LIBCAF_CORE_SRCS ...@@ -99,6 +99,7 @@ set(LIBCAF_CORE_SRCS
src/sequencer.cpp src/sequencer.cpp
src/serializer.cpp src/serializer.cpp
src/set_thread_name.cpp src/set_thread_name.cpp
src/settings.cpp
src/shared_spinlock.cpp src/shared_spinlock.cpp
src/simple_actor_clock.cpp src/simple_actor_clock.cpp
src/skip.cpp src/skip.cpp
......
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include "caf/fwd.hpp" #include "caf/fwd.hpp"
#include "caf/is_typed_actor.hpp" #include "caf/is_typed_actor.hpp"
#include "caf/named_actor_config.hpp" #include "caf/named_actor_config.hpp"
#include "caf/settings.hpp"
#include "caf/stream.hpp" #include "caf/stream.hpp"
#include "caf/thread_hook.hpp" #include "caf/thread_hook.hpp"
#include "caf/type_erased_value.hpp" #include "caf/type_erased_value.hpp"
...@@ -103,7 +104,7 @@ public: ...@@ -103,7 +104,7 @@ public:
// -- properties ------------------------------------------------------------- // -- properties -------------------------------------------------------------
/// @private /// @private
dictionary<config_value::dictionary> content; settings content;
/// Sets a config by using its INI name `config_name` to `config_value`. /// Sets a config by using its INI name `config_name` to `config_value`.
template <class T> template <class T>
...@@ -113,25 +114,23 @@ public: ...@@ -113,25 +114,23 @@ public:
// -- modifiers -------------------------------------------------------------- // -- modifiers --------------------------------------------------------------
/// Parses `args` as tuple of strings containing CLI options /// Parses `args` as tuple of strings containing CLI options and `ini_stream`
/// and `ini_stream` as INI formatted input stream. /// as INI formatted input stream.
actor_system_config& parse(string_list args, std::istream& ini); error parse(string_list args, std::istream& ini);
/// Parses `args` as tuple of strings containing CLI options and tries to /// Parses `args` as tuple of strings containing CLI options and tries to
/// open `ini_file_cstr` as INI formatted config file. The parsers tries to /// open `ini_file_cstr` as INI formatted config file. The parsers tries to
/// open `caf-application.ini` if `ini_file_cstr` is `nullptr`. /// open `caf-application.ini` if `ini_file_cstr` is `nullptr`.
actor_system_config& parse(string_list args, error parse(string_list args, const char* ini_file_cstr = nullptr);
const char* ini_file_cstr = nullptr);
/// Parses the CLI options `{argc, argv}` and /// Parses the CLI options `{argc, argv}` and `ini_stream` as INI formatted
/// `ini_stream` as INI formatted input stream. /// input stream.
actor_system_config& parse(int argc, char** argv, std::istream& ini); error parse(int argc, char** argv, std::istream& ini);
/// Parses the CLI options `{argc, argv}` and tries to open `ini_file_cstr` /// Parses the CLI options `{argc, argv}` and tries to open `ini_file_cstr`
/// as INI formatted config file. The parsers tries to open /// as INI formatted config file. The parsers tries to open
/// `caf-application.ini` if `ini_file_cstr` is `nullptr`. /// `caf-application.ini` if `ini_file_cstr` is `nullptr`.
actor_system_config& parse(int argc, char** argv, error parse(int argc, char** argv, const char* ini_file_cstr = nullptr);
const char* ini_file_cstr = nullptr);
/// Allows other nodes to spawn actors created by `fun` /// Allows other nodes to spawn actors created by `fun`
/// dynamically by using `name` as identifier. /// dynamically by using `name` as identifier.
...@@ -337,8 +336,43 @@ private: ...@@ -337,8 +336,43 @@ private:
static std::string render_exit_reason(uint8_t, atom_value, const message&); static std::string render_exit_reason(uint8_t, atom_value, const message&);
static std::string render_pec(uint8_t, atom_value, const message&);
void extract_config_file_path(string_list& args); void extract_config_file_path(string_list& args);
}; };
} // namespace caf /// @private
const settings& content(const actor_system_config& cfg);
/// Tries to retrieve the value associated to `name` from `cfg`.
/// @relates config_value
template <class T>
optional<T> get_if(const actor_system_config* cfg, string_view name) {
return get_if<T>(&content(*cfg), name);
}
/// Retrieves the value associated to `name` from `cfg`.
/// @relates config_value
template <class T>
T get(const actor_system_config& cfg, string_view name) {
return get<T>(content(cfg), name);
}
/// Retrieves the value associated to `name` from `cfg` or returns
/// `default_value`.
/// @relates config_value
template <class T, class E = detail::enable_if_t<!std::is_pointer<T>::value>>
T get_or(const actor_system_config& cfg, string_view name,
const T& default_value) {
return get_or(content(cfg), name, default_value);
}
/// Retrieves the value associated to `name` from `cfg` or returns
/// `default_value`.
/// @relates config_value
inline std::string get_or(const actor_system_config& cfg, string_view name,
string_view default_value) {
return get_or(content(cfg), name, default_value);
}
} // namespace caf
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
namespace caf { namespace caf {
/// A set of `config_option` objects that parses CLI arguments into a /// A set of `config_option` objects that parses CLI arguments into a
/// `config_value::dictionary`. /// `settings` object.
class config_option_set { class config_option_set {
public: public:
// -- member types ----------------------------------------------------------- // -- member types -----------------------------------------------------------
...@@ -56,12 +56,6 @@ public: ...@@ -56,12 +56,6 @@ public:
/// An iterator over ::config_option unique pointers. /// An iterator over ::config_option unique pointers.
using const_iterator = option_vector::const_iterator; using const_iterator = option_vector::const_iterator;
/// Maps string keys to arbitrary (config) values.
using dictionary = caf::dictionary<config_value>;
/// Categorized settings.
using config_map = caf::dictionary<dictionary>;
// -- properties ------------------------------------------------------------- // -- properties -------------------------------------------------------------
/// Returns the first `config_option` that matches the CLI name. /// Returns the first `config_option` that matches the CLI name.
...@@ -174,11 +168,11 @@ public: ...@@ -174,11 +168,11 @@ public:
// -- parsing ---------------------------------------------------------------- // -- parsing ----------------------------------------------------------------
/// Parses a given range as CLI arguments into `config`. /// Parses a given range as CLI arguments into `config`.
parse_result parse(config_map& config, argument_iterator begin, parse_result parse(settings& config, argument_iterator begin,
argument_iterator end) const; argument_iterator end) const;
/// Parses a given range as CLI arguments into `config`. /// Parses a given range as CLI arguments into `config`.
parse_result parse(config_map& config, parse_result parse(settings& config,
const std::vector<std::string>& args) const; const std::vector<std::string>& args) const;
private: private:
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <cstdint> #include <cstdint>
#include <map> #include <map>
#include <string> #include <string>
#include <type_traits>
#include <vector> #include <vector>
#include "caf/atom.hpp" #include "caf/atom.hpp"
...@@ -32,6 +33,7 @@ ...@@ -32,6 +33,7 @@
#include "caf/optional.hpp" #include "caf/optional.hpp"
#include "caf/raise_error.hpp" #include "caf/raise_error.hpp"
#include "caf/string_algorithms.hpp" #include "caf/string_algorithms.hpp"
#include "caf/string_view.hpp"
#include "caf/sum_type.hpp" #include "caf/sum_type.hpp"
#include "caf/sum_type_access.hpp" #include "caf/sum_type_access.hpp"
#include "caf/sum_type_token.hpp" #include "caf/sum_type_token.hpp"
...@@ -111,6 +113,12 @@ public: ...@@ -111,6 +113,12 @@ public:
/// already is a list. /// already is a list.
void convert_to_list(); void convert_to_list();
/// Returns the value as a list, converting it to one if needed.
list& as_list();
/// Returns the value as a dictionary, converting it to one if needed.
dictionary& as_dictionary();
/// Appends `x` to a list. Converts this config value to a list first by /// Appends `x` to a list. Converts this config value to a list first by
/// calling `convert_to_list` if needed. /// calling `convert_to_list` if needed.
void append(config_value x); void append(config_value x);
...@@ -174,12 +182,6 @@ private: ...@@ -174,12 +182,6 @@ private:
variant_type data_; variant_type data_;
}; };
// -- related type aliases -----------------------------------------------------
/// Organizes config values into categories.
/// @relates config_value
using config_value_map = dictionary<config_value::dictionary>;
// -- SumType-like access ------------------------------------------------------ // -- SumType-like access ------------------------------------------------------
/// @relates config_value /// @relates config_value
...@@ -401,168 +403,6 @@ struct config_value_access<dictionary<V>> { ...@@ -401,168 +403,6 @@ struct config_value_access<dictionary<V>> {
// -- SumType-like access of dictionary values --------------------------------- // -- SumType-like access of dictionary values ---------------------------------
/// Tries to retrieve the value associated to `name` from `xs`.
/// @relates config_value
template <class T>
optional<T> get_if(const config_value::dictionary* xs, string_view name) {
// Split the name into a path.
std::vector<string_view> path;
split(path, name, ".");
// Sanity check.
if (path.size() == 0)
return none;
// Resolve path, i.e., find the requested submap.
auto current = xs;
auto leaf = path.end() - 1;
for (auto i = path.begin(); i != leaf; ++i) {
auto j = current->find(*i);
if (j == current->end())
return none;
current = caf::get_if<config_value::dictionary>(&j->second);
if (current == nullptr)
return none;
}
// Get the leaf value.
auto j = current->find(*leaf);
if (j == current->end())
return none;
auto result = caf::get_if<T>(&j->second);
if (result)
return *result;
return none;
}
/// Retrieves the value associated to `name` from `xs`.
/// @relates config_value
template <class T>
T get(const config_value::dictionary& xs, string_view name) {
auto result = get_if<T>(&xs, name);
if (result)
return std::move(*result);
CAF_RAISE_ERROR("invalid type or name found");
}
/// Retrieves the value associated to `name` from `xs` or returns
/// `default_value`.
/// @relates config_value
template <class T, class E = detail::enable_if_t<!std::is_pointer<T>::value>>
T get_or(const config_value::dictionary& xs, string_view name,
const T& default_value) {
auto result = get_if<T>(&xs, name);
if (result)
return std::move(*result);
return default_value;
}
/// Retrieves the value associated to `name` from `xs` or returns
/// `default_value`.
/// @relates config_value
std::string get_or(const config_value::dictionary& xs, string_view name,
const char* default_value);
/// Tries to retrieve the value associated to `name` from `xs`.
/// @relates config_value
template <class T>
optional<T> get_if(const config_value_map* xs, string_view name) {
// Get the category.
auto pos = name.find('.');
if (pos == std::string::npos) {
auto i = xs->find("global");
if (i == xs->end())
return none;
return get_if<T>(&i->second, name);
}
auto i = xs->find(name.substr(0, pos));
if (i == xs->end())
return none;
return get_if<T>(&i->second, name.substr(pos + 1));
}
/// Retrieves the value associated to `name` from `xs`.
/// @relates config_value
template <class T>
T get(const config_value_map& xs, string_view name) {
auto result = get_if<T>(&xs, name);
if (result)
return std::move(*result);
CAF_RAISE_ERROR("invalid type or name found");
}
/// Retrieves the value associated to `name` from `xs` or returns
/// `default_value`.
/// @relates config_value
template <class T, class E = detail::enable_if_t<!std::is_pointer<T>::value>>
T get_or(const config_value_map& xs, string_view name, const T& default_value) {
auto result = get_if<T>(&xs, name);
if (result)
return std::move(*result);
return default_value;
}
/// Retrieves the value associated to `name` from `xs` or returns
/// `default_value`.
/// @relates config_value
std::string get_or(const config_value_map& xs, string_view name,
const char* default_value);
/// Tries to retrieve the value associated to `name` from `cfg`.
/// @relates config_value
template <class T>
optional<T> get_if(const actor_system_config* cfg, string_view name) {
return get_if<T>(&content(*cfg), name);
}
/// Retrieves the value associated to `name` from `cfg`.
/// @relates config_value
template <class T>
T get(const actor_system_config& cfg, string_view name) {
return get<T>(content(cfg), name);
}
/// Retrieves the value associated to `name` from `cfg` or returns
/// `default_value`.
/// @relates config_value
template <class T, class E = detail::enable_if_t<!std::is_pointer<T>::value>>
T get_or(const actor_system_config& cfg, string_view name,
const T& default_value) {
return get_or(content(cfg), name, default_value);
}
std::string get_or(const actor_system_config& cfg, string_view name,
const char* default_value);
/// @private
void put_impl(config_value::dictionary& dict,
const std::vector<string_view>& path, config_value& value);
/// @private
void put_impl(config_value::dictionary& dict, string_view key,
config_value& value);
/// @private
void put_impl(dictionary<config_value::dictionary>& dict, string_view key,
config_value& value);
/// Converts `value` to a `config_value` and assigns it to `key`.
/// @param dict Dictionary of key-value pairs.
/// @param key Human-readable nested keys in the form `category.key`.
/// @param value New value for given `key`.
template <class T>
void put(dictionary<config_value::dictionary>& dict, string_view key,
T&& value) {
config_value tmp{std::forward<T>(value)};
put_impl(dict, key, tmp);
}
/// Inserts a new list named `name` into the dictionary `xs` and returns
/// a reference to it. Overrides existing entries with the same name.
config_value::list& put_list(config_value::dictionary& xs, std::string name);
/// Inserts a new list named `name` into the dictionary `xs` and returns
/// a reference to it. Overrides existing entries with the same name.
config_value::dictionary& put_dictionary(config_value::dictionary& xs,
std::string name);
/// @relates config_value /// @relates config_value
bool operator<(const config_value& x, const config_value& y); bool operator<(const config_value& x, const config_value& y);
...@@ -595,4 +435,3 @@ typename Inspector::result_type inspect(Inspector& f, config_value& x) { ...@@ -595,4 +435,3 @@ typename Inspector::result_type inspect(Inspector& f, config_value& x) {
} }
} // namespace caf } // namespace caf
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <cstddef> #include <cstddef>
#include "caf/atom.hpp" #include "caf/atom.hpp"
#include "caf/string_view.hpp"
#include "caf/timestamp.hpp" #include "caf/timestamp.hpp"
// -- hard-coded default values for various CAF options ------------------------ // -- hard-coded default values for various CAF options ------------------------
...@@ -40,7 +41,7 @@ extern const timespan credit_round_interval; ...@@ -40,7 +41,7 @@ extern const timespan credit_round_interval;
namespace scheduler { namespace scheduler {
extern const atom_value policy; extern const atom_value policy;
extern const char* profiling_output_file; extern string_view profiling_output_file;
extern const size_t max_threads; extern const size_t max_threads;
extern const size_t max_throughput; extern const size_t max_throughput;
extern const timespan profiling_resolution; extern const timespan profiling_resolution;
...@@ -61,19 +62,19 @@ extern const timespan relaxed_sleep_duration; ...@@ -61,19 +62,19 @@ extern const timespan relaxed_sleep_duration;
namespace logger { namespace logger {
extern const char* component_filter; extern string_view component_filter;
extern const atom_value console; extern const atom_value console;
extern const char* console_format; extern string_view console_format;
extern const atom_value console_verbosity; extern const atom_value console_verbosity;
extern const char* file_format; extern string_view file_format;
extern const char* file_name; extern string_view file_name;
extern const atom_value file_verbosity; extern const atom_value file_verbosity;
} // namespace logger } // namespace logger
namespace middleman { namespace middleman {
extern const char* app_identifier; extern string_view app_identifier;
extern const atom_value network_backend; extern const atom_value network_backend;
extern const size_t max_consecutive_reads; extern const size_t max_consecutive_reads;
extern const size_t heartbeat_interval; extern const size_t heartbeat_interval;
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "caf/config_option_set.hpp" #include "caf/config_option_set.hpp"
#include "caf/config_value.hpp" #include "caf/config_value.hpp"
#include "caf/dictionary.hpp" #include "caf/dictionary.hpp"
#include "caf/settings.hpp"
namespace caf { namespace caf {
namespace detail { namespace detail {
...@@ -191,7 +192,7 @@ public: ...@@ -191,7 +192,7 @@ public:
// -- constructors, destructors, and assignment operators -------------------- // -- constructors, destructors, and assignment operators --------------------
ini_consumer(config_option_set& options, config_map& cfg); ini_consumer(config_option_set& options, settings& cfg);
ini_consumer(ini_consumer&&) = default; ini_consumer(ini_consumer&&) = default;
...@@ -207,7 +208,7 @@ private: ...@@ -207,7 +208,7 @@ private:
// -- member variables ------------------------------------------------------- // -- member variables -------------------------------------------------------
config_option_set& options_; config_option_set& options_;
config_map& cfg_; settings& cfg_;
std::string current_key; std::string current_key;
std::vector<error> warnings_; std::vector<error> warnings_;
}; };
......
...@@ -366,13 +366,4 @@ bool operator>=(const dictionary<T>& xs, const dictionary<T>& ys) { ...@@ -366,13 +366,4 @@ bool operator>=(const dictionary<T>& xs, const dictionary<T>& ys) {
return xs.container() >= ys.container(); return xs.container() >= ys.container();
} }
// -- free functions -----------------------------------------------------------
/// Convenience function for calling `dict.insert_or_assign(key, value)`.
// @relates dictionary
template <class T, class V>
void put(dictionary<T>& dict, string_view key, V&& value) {
dict.insert_or_assign(key, std::forward<V>(value));
}
} // namespace caf } // namespace caf
...@@ -174,13 +174,12 @@ using ip_address = ipv6_address; ...@@ -174,13 +174,12 @@ using ip_address = ipv6_address;
using ip_subnet = ipv6_subnet; using ip_subnet = ipv6_subnet;
using stream_slot = uint16_t; using stream_slot = uint16_t;
using config_value_map = dictionary<dictionary<config_value>>;
using settings = dictionary<config_value>; using settings = dictionary<config_value>;
// -- functions ---------------------------------------------------------------- // -- functions ----------------------------------------------------------------
/// @relates actor_system_config /// @relates actor_system_config
const dictionary<dictionary<config_value>>& content(const actor_system_config&); const settings& content(const actor_system_config&);
// -- intrusive containers ----------------------------------------------------- // -- intrusive containers -----------------------------------------------------
......
...@@ -65,10 +65,18 @@ enum class pec : uint8_t { ...@@ -65,10 +65,18 @@ enum class pec : uint8_t {
illegal_category, illegal_category,
}; };
/// Returns an error object from given error code.
error make_error(pec code); error make_error(pec code);
/// Returns an error object from given error code with additional context
/// information for where the parser stopped in the input.
error make_error(pec code, size_t line, size_t column); error make_error(pec code, size_t line, size_t column);
/// Returns an error object from given error code with additional context
/// information for where the parser stopped in the argument.
error make_error(pec code, std::string argument);
/// @relates pec
const char* to_string(pec x); const char* to_string(pec x);
} // namespace caf } // namespace caf
...@@ -20,6 +20,9 @@ ...@@ -20,6 +20,9 @@
#include "caf/config_value.hpp" #include "caf/config_value.hpp"
#include "caf/dictionary.hpp" #include "caf/dictionary.hpp"
#include "caf/optional.hpp"
#include "caf/raise_error.hpp"
#include "caf/string_view.hpp"
namespace caf { namespace caf {
...@@ -27,4 +30,74 @@ namespace caf { ...@@ -27,4 +30,74 @@ namespace caf {
/// @relates config_value /// @relates config_value
using settings = dictionary<config_value>; using settings = dictionary<config_value>;
/// Tries to retrieve the value associated to `name` from `xs`.
/// @relates config_value
template <class T>
optional<T> get_if(const settings* xs, string_view name) {
// Access the key directly unless the user specified a dot-separated path.
auto pos = name.find('.');
if (pos == std::string::npos) {
auto i = xs->find(name);
if (i == xs->end())
return none;
// We can't simply return the result here, because it might be a pointer.
auto result = get_if<T>(&i->second);
if (result)
return *result;
return none;
}
// We're dealing with a `<category>.<key>`-formatted string, extract the
// sub-settings by category and recurse.
auto i = xs->find(name.substr(0, pos));
if (i == xs->end() || !holds_alternative<config_value::dictionary>(i->second))
return none;
return get_if<T>(&get<config_value::dictionary>(i->second),
name.substr(pos + 1));
}
template <class T>
T get(const settings& xs, string_view name) {
auto result = get_if<T>(&xs, name);
CAF_ASSERT(result != none);
return std::move(*result);
}
template <class T,
class = typename std::enable_if<!std::is_pointer<T>::value>::type>
T get_or(const settings& xs, string_view name, T default_value) {
auto result = get_if<T>(&xs, name);
if (result)
return std::move(*result);
return std::move(default_value);
}
std::string get_or(const settings& xs, string_view name,
string_view default_value);
/// @private
void put_impl(settings& dict, const std::vector<string_view>& path,
config_value& value);
/// @private
void put_impl(settings& dict, string_view key,
config_value& value);
/// Converts `value` to a `config_value` and assigns it to `key`.
/// @param dict Dictionary of key-value pairs.
/// @param key Human-readable nested keys in the form `category.key`.
/// @param value New value for given `key`.
template <class T>
void put(settings& dict, string_view key, T&& value) {
config_value tmp{std::forward<T>(value)};
put_impl(dict, key, tmp);
}
/// Inserts a new list named `name` into the dictionary `xs` and returns
/// a reference to it. Overrides existing entries with the same name.
config_value::list& put_list(settings& xs, std::string name);
/// Inserts a new list named `name` into the dictionary `xs` and returns
/// a reference to it. Overrides existing entries with the same name.
config_value::dictionary& put_dictionary(settings& xs, std::string name);
} // namespace caf } // namespace caf
...@@ -32,8 +32,6 @@ ...@@ -32,8 +32,6 @@
#include "caf/detail/parser/read_string.hpp" #include "caf/detail/parser/read_string.hpp"
#include "caf/message_builder.hpp" #include "caf/message_builder.hpp"
CAF_PUSH_DEPRECATED_WARNING
namespace caf { namespace caf {
actor_system_config::~actor_system_config() { actor_system_config::~actor_system_config() {
...@@ -57,9 +55,9 @@ actor_system_config::actor_system_config() ...@@ -57,9 +55,9 @@ actor_system_config::actor_system_config()
add_message_type_impl<std::vector<actor_addr>>("std::vector<@addr>"); add_message_type_impl<std::vector<actor_addr>>("std::vector<@addr>");
add_message_type_impl<std::vector<atom_value>>("std::vector<@atom>"); add_message_type_impl<std::vector<atom_value>>("std::vector<@atom>");
add_message_type_impl<std::vector<message>>("std::vector<@message>"); add_message_type_impl<std::vector<message>>("std::vector<@message>");
add_message_type_impl<config_value_map>("config_value_map"); add_message_type_impl<settings>("settings");
add_message_type_impl<config_value::list>("config_value::list"); add_message_type_impl<config_value::list>("std::vector<@config_value>");
add_message_type_impl<config_value::dictionary>("config_value::dictionary"); add_message_type_impl<config_value::dictionary>("dictionary<@config_value>");
// (1) hard-coded defaults // (1) hard-coded defaults
stream_desired_batch_complexity = defaults::stream::desired_batch_complexity; stream_desired_batch_complexity = defaults::stream::desired_batch_complexity;
stream_max_batch_delay = defaults::stream::max_batch_delay; stream_max_batch_delay = defaults::stream::max_batch_delay;
...@@ -177,16 +175,15 @@ actor_system_config::make_help_text(const std::vector<message::cli_arg>& xs) { ...@@ -177,16 +175,15 @@ actor_system_config::make_help_text(const std::vector<message::cli_arg>& xs) {
return oss.str(); return oss.str();
} }
actor_system_config& actor_system_config::parse(int argc, char** argv, error actor_system_config::parse(int argc, char** argv,
const char* ini_file_cstr) { const char* ini_file_cstr) {
string_list args; string_list args;
if (argc > 1) if (argc > 1)
args.assign(argv + 1, argv + argc); args.assign(argv + 1, argv + argc);
return parse(std::move(args), ini_file_cstr); return parse(std::move(args), ini_file_cstr);
} }
actor_system_config& actor_system_config::parse(int argc, char** argv, error actor_system_config::parse(int argc, char** argv, std::istream& ini) {
std::istream& ini) {
string_list args; string_list args;
if (argc > 1) if (argc > 1)
args.assign(argv + 1, argv + argc); args.assign(argv + 1, argv + argc);
...@@ -229,16 +226,7 @@ bool operator!=(ini_iter iter, ini_sentinel) { ...@@ -229,16 +226,7 @@ bool operator!=(ini_iter iter, ini_sentinel) {
} // namespace <anonymous> } // namespace <anonymous>
actor_system_config& actor_system_config::parse(string_list args, error actor_system_config::parse(string_list args, std::istream& ini) {
std::istream& ini) {
// Insert possibly user-defined values into the map to respect overrides to
// member variables.
// TODO: remove with CAF 0.17
for (auto& opt : custom_options_) {
auto val = opt.get();
if (val)
content[opt.category()][opt.long_name()] = std::move(*val);
}
// Content of the INI file overrides hard-coded defaults. // Content of the INI file overrides hard-coded defaults.
if (ini.good()) { if (ini.good()) {
detail::ini_consumer consumer{custom_options_, content}; detail::ini_consumer consumer{custom_options_, content};
...@@ -246,14 +234,14 @@ actor_system_config& actor_system_config::parse(string_list args, ...@@ -246,14 +234,14 @@ actor_system_config& actor_system_config::parse(string_list args,
res.i = ini_iter{&ini}; res.i = ini_iter{&ini};
detail::parser::read_ini(res, consumer); detail::parser::read_ini(res, consumer);
if (res.i != res.e) if (res.i != res.e)
std::cerr << "*** error in config file [line " << res.line << " col " return make_error(res.code, res.line, res.column);
<< res.column << "]: " << to_string(res.code) << std::endl;
} }
// CLI options override the content of the INI file. // CLI options override the content of the INI file.
using std::make_move_iterator; using std::make_move_iterator;
auto res = custom_options_.parse(content, args); auto res = custom_options_.parse(content, args);
if (res.second != args.end()) { if (res.second != args.end()) {
if (res.first != pec::success) { if (res.first != pec::success) {
return make_error(res.first, *res.second);
std::cerr << "error: at argument \"" << *res.second std::cerr << "error: at argument \"" << *res.second
<< "\": " << to_string(res.first) << std::endl; << "\": " << to_string(res.first) << std::endl;
cli_helptext_printed = true; cli_helptext_printed = true;
...@@ -274,19 +262,20 @@ actor_system_config& actor_system_config::parse(string_list args, ...@@ -274,19 +262,20 @@ actor_system_config& actor_system_config::parse(string_list args,
// Generate INI dump if needed. // Generate INI dump if needed.
if (!cli_helptext_printed && get_or(content, "global.dump-config", false)) { if (!cli_helptext_printed && get_or(content, "global.dump-config", false)) {
for (auto& category : content) { for (auto& category : content) {
std::cout << '[' << category.first << "]\n"; if (auto dict = get_if<config_value::dictionary>(&category.second)) {
for (auto& kvp : category.second) std::cout << '[' << category.first << "]\n";
if (kvp.first != "dump-config") for (auto& kvp : *dict)
std::cout << kvp.first << '=' << to_string(kvp.second) << '\n'; if (kvp.first != "dump-config")
std::cout << kvp.first << '=' << to_string(kvp.second) << '\n';
}
} }
std::cout << std::flush; std::cout << std::flush;
cli_helptext_printed = true; cli_helptext_printed = true;
} }
return *this; return none;
} }
actor_system_config& actor_system_config::parse(string_list args, error actor_system_config::parse(string_list args, const char* ini_file_cstr) {
const char* ini_file_cstr) {
// Override default config file name if set by user. // Override default config file name if set by user.
if (ini_file_cstr != nullptr) if (ini_file_cstr != nullptr)
config_file_path = ini_file_cstr; config_file_path = ini_file_cstr;
...@@ -313,7 +302,8 @@ actor_system_config& actor_system_config::set_impl(string_view name, ...@@ -313,7 +302,8 @@ actor_system_config& actor_system_config::set_impl(string_view name,
auto opt = custom_options_.qualified_name_lookup(name); auto opt = custom_options_.qualified_name_lookup(name);
if (opt != nullptr && opt->check(value) == none) { if (opt != nullptr && opt->check(value) == none) {
opt->store(value); opt->store(value);
content[opt->category()][opt->long_name()] = std::move(value); auto& dict = content[opt->category()].as_dictionary();
dict[opt->long_name()] = std::move(value);
} }
return *this; return *this;
} }
...@@ -338,6 +328,13 @@ std::string actor_system_config::render_exit_reason(uint8_t x, atom_value, ...@@ -338,6 +328,13 @@ std::string actor_system_config::render_exit_reason(uint8_t x, atom_value,
meta::omittable_if_empty(), xs); meta::omittable_if_empty(), xs);
} }
std::string actor_system_config::render_pec(uint8_t x, atom_value,
const message& xs) {
auto tmp = static_cast<exit_reason>(x);
return deep_to_string(meta::type_name("parser_error"), tmp,
meta::omittable_if_empty(), xs);
}
void actor_system_config::extract_config_file_path(string_list& args) { void actor_system_config::extract_config_file_path(string_list& args) {
static constexpr const char needle[] = "--caf#config-file="; static constexpr const char needle[] = "--caf#config-file=";
auto last = args.end(); auto last = args.end();
...@@ -375,11 +372,8 @@ void actor_system_config::extract_config_file_path(string_list& args) { ...@@ -375,11 +372,8 @@ void actor_system_config::extract_config_file_path(string_list& args) {
args.erase(i); args.erase(i);
} }
const dictionary<dictionary<config_value>>& const settings& content(const actor_system_config& cfg) {
content(const actor_system_config& cfg) {
return cfg.content; return cfg.content;
} }
} // namespace caf } // namespace caf
CAF_POP_WARNINGS
...@@ -111,7 +111,7 @@ std::string config_option_set::help_text(bool global_only) const { ...@@ -111,7 +111,7 @@ std::string config_option_set::help_text(bool global_only) const {
return std::move(builder.result); return std::move(builder.result);
} }
auto config_option_set::parse(config_map& config, argument_iterator first, auto config_option_set::parse(settings& config, argument_iterator first,
argument_iterator last) const argument_iterator last) const
-> std::pair<pec, argument_iterator> { -> std::pair<pec, argument_iterator> {
// Sanity check. // Sanity check.
...@@ -124,7 +124,10 @@ auto config_option_set::parse(config_map& config, argument_iterator first, ...@@ -124,7 +124,10 @@ auto config_option_set::parse(config_map& config, argument_iterator first,
auto opt_name = opt.long_name(); auto opt_name = opt.long_name();
auto opt_ctg = opt.category(); auto opt_ctg = opt.category();
// Try inserting a new submap into the config or fill existing one. // Try inserting a new submap into the config or fill existing one.
auto& submap = config[opt_ctg]; auto& entry = config[opt_ctg];
if (!holds_alternative<config_value::dictionary>(entry))
entry = config_value::dictionary{};
auto& submap = get<config_value::dictionary>(entry);
// Flags only consume the current element. // Flags only consume the current element.
if (opt.is_flag()) { if (opt.is_flag()) {
if (arg_begin != arg_end) if (arg_begin != arg_end)
...@@ -223,7 +226,7 @@ auto config_option_set::parse(config_map& config, argument_iterator first, ...@@ -223,7 +226,7 @@ auto config_option_set::parse(config_map& config, argument_iterator first,
} }
config_option_set::parse_result config_option_set::parse_result
config_option_set::parse(config_map& config, config_option_set::parse(settings& config,
const std::vector<string>& args) const { const std::vector<string>& args) const {
return parse(config, args.begin(), args.end()); return parse(config, args.begin(), args.end());
} }
......
...@@ -100,6 +100,17 @@ void config_value::convert_to_list() { ...@@ -100,6 +100,17 @@ void config_value::convert_to_list() {
data_ = std::vector<config_value>{std::move(tmp)}; data_ = std::vector<config_value>{std::move(tmp)};
} }
config_value::list& config_value::as_list() {
convert_to_list();
return get<list>(*this);
}
config_value::dictionary& config_value::as_dictionary() {
if (!holds_alternative<dictionary>(*this))
*this = dictionary{};
return get<dictionary>(*this);
}
void config_value::append(config_value x) { void config_value::append(config_value x) {
convert_to_list(); convert_to_list();
get<list>(data_).emplace_back(std::move(x)); get<list>(data_).emplace_back(std::move(x));
...@@ -125,81 +136,5 @@ std::string to_string(const config_value& x) { ...@@ -125,81 +136,5 @@ std::string to_string(const config_value& x) {
return deep_to_string(x.get_data()); return deep_to_string(x.get_data());
} }
std::string get_or(const config_value::dictionary& xs, const std::string& name,
const char* default_value) {
auto result = get_if<std::string>(&xs, name);
if (result)
return std::move(*result);
return default_value;
}
std::string get_or(const dictionary<config_value::dictionary>& xs,
string_view name, const char* default_value) {
auto result = get_if<std::string>(&xs, name);
if (result)
return std::move(*result);
return default_value;
}
std::string get_or(const actor_system_config& cfg, string_view name,
const char* default_value) {
return get_or(content(cfg), name, default_value);
}
void put_impl(config_value::dictionary& dict,
const std::vector<string_view>& path, config_value& value) {
// Sanity check.
if (path.empty())
return;
// Navigate path.
auto last = path.end();
auto back = last - 1;
auto current = &dict;
// Resolve path by navigating the map-of-maps of create the necessary layout
// when needed.
for (auto i = path.begin(); i != back; ++i) {
auto iter = current->emplace(*i, config_value::dictionary{}).first;
if (auto val = get_if<config_value::dictionary>(&iter->second)) {
current = val;
} else {
iter->second = config_value::dictionary{};
current = &get<config_value::dictionary>(iter->second);
}
}
// Set key-value pair on the leaf.
current->insert_or_assign(*back, std::move(value));
}
void put_impl(config_value::dictionary& dict, string_view key,
config_value& value) {
std::vector<string_view> path;
split(path, key, ".");
put_impl(dict, path, value);
}
void put_impl(dictionary<config_value::dictionary>& dict, string_view key,
config_value& value) {
// Split the name into a path.
std::vector<string_view> path;
split(path, key, ".");
// Sanity check. At the very least, we need a category and a key.
if (path.size() < 2)
return;
auto category = path.front();
path.erase(path.begin());
put_impl(dict[category], path, value);
}
config_value::list& put_list(config_value::dictionary& xs, std::string name) {
auto i = xs.insert_or_assign(std::move(name), config_value::list{});
return get<config_value::list>(i.first->second);
}
config_value::dictionary& put_dictionary(config_value::dictionary& xs,
std::string name) {
auto i = xs.insert_or_assign(std::move(name), config_value::dictionary{});
return get<config_value::dictionary>(i.first->second);
}
} // namespace caf } // namespace caf
...@@ -53,7 +53,7 @@ const timespan credit_round_interval = ms(10); ...@@ -53,7 +53,7 @@ const timespan credit_round_interval = ms(10);
namespace scheduler { namespace scheduler {
const atom_value policy = atom("stealing"); const atom_value policy = atom("stealing");
const char* profiling_output_file = ""; string_view profiling_output_file = "";
const size_t max_threads = std::max(std::thread::hardware_concurrency(), 4u); const size_t max_threads = std::max(std::thread::hardware_concurrency(), 4u);
const size_t max_throughput = std::numeric_limits<size_t>::max(); const size_t max_throughput = std::numeric_limits<size_t>::max();
const timespan profiling_resolution = ms(100); const timespan profiling_resolution = ms(100);
...@@ -74,19 +74,19 @@ const timespan relaxed_sleep_duration = ms(10); ...@@ -74,19 +74,19 @@ const timespan relaxed_sleep_duration = ms(10);
namespace logger { namespace logger {
const char* component_filter = ""; string_view component_filter = "";
const atom_value console = atom("none"); const atom_value console = atom("none");
const char* console_format = "%m"; string_view console_format = "%m";
const atom_value console_verbosity = atom("trace"); const atom_value console_verbosity = atom("trace");
const char* file_format = "%r %c %p %a %t %C %M %F:%L %m%n"; string_view file_format = "%r %c %p %a %t %C %M %F:%L %m%n";
const char* file_name = "actor_log_[PID]_[TIMESTAMP]_[NODE].log"; string_view file_name = "actor_log_[PID]_[TIMESTAMP]_[NODE].log";
const atom_value file_verbosity = atom("trace"); const atom_value file_verbosity = atom("trace");
} // namespace logger } // namespace logger
namespace middleman { namespace middleman {
const char* app_identifier = ""; string_view app_identifier = "";
const atom_value network_backend = atom("default"); const atom_value network_backend = atom("default");
const size_t max_consecutive_reads = 50; const size_t max_consecutive_reads = 50;
const size_t heartbeat_interval = 0; const size_t heartbeat_interval = 0;
......
...@@ -153,7 +153,7 @@ ini_consumer* ini_category_consumer::dparent() { ...@@ -153,7 +153,7 @@ ini_consumer* ini_category_consumer::dparent() {
// -- ini_consumer ------------------------------------------------------------- // -- ini_consumer -------------------------------------------------------------
ini_consumer::ini_consumer(config_option_set& options, config_map& cfg) ini_consumer::ini_consumer(config_option_set& options, settings& cfg)
: options_(options), : options_(options),
cfg_(cfg) { cfg_(cfg) {
// nop // nop
...@@ -168,13 +168,15 @@ void ini_consumer::key(std::string name) { ...@@ -168,13 +168,15 @@ void ini_consumer::key(std::string name) {
} }
void ini_consumer::value_impl(config_value&& x) { void ini_consumer::value_impl(config_value&& x) {
auto dict = get_if<config_value::dictionary>(&x); using dict_type = config_value::dictionary;
if (dict != nullptr && !dict->empty()) { auto dict = get_if<dict_type>(&x);
auto& dst = cfg_.emplace(current_key, dict_type{}).first->second;
if (dict != nullptr && !dict->empty() && holds_alternative<dict_type>(dst)) {
auto& dst_dict = get<dict_type>(dst);
// We need to "merge" values into the destination, because it can already // We need to "merge" values into the destination, because it can already
// contain any number of unrelated entries. // contain any number of unrelated entries.
auto& dst = cfg_[current_key];
for (auto& entry : *dict) for (auto& entry : *dict)
dst.insert_or_assign(entry.first, std::move(entry.second)); dst_dict.insert_or_assign(entry.first, std::move(entry.second));
} }
} }
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "caf/pec.hpp" #include "caf/pec.hpp"
#include "caf/config_value.hpp"
#include "caf/error.hpp" #include "caf/error.hpp"
#include "caf/make_message.hpp" #include "caf/make_message.hpp"
...@@ -53,9 +54,18 @@ error make_error(pec code) { ...@@ -53,9 +54,18 @@ error make_error(pec code) {
} }
error make_error(pec code, size_t line, size_t column) { error make_error(pec code, size_t line, size_t column) {
config_value::dictionary context;
context["line"] = line;
context["column"] = column;
return {static_cast<uint8_t>(code), atom("parser"), return {static_cast<uint8_t>(code), atom("parser"),
make_message(static_cast<uint32_t>(line), make_message(std::move(context))};
static_cast<uint32_t>(column))}; }
error make_error(pec code, std::string argument) {
config_value::dictionary context;
context["argument"] = std::move(argument);
return {static_cast<uint8_t>(code), atom("parser"),
make_message(std::move(context))};
} }
const char* to_string(pec x) { const char* to_string(pec x) {
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "caf/test/dsl.hpp" #include "caf/test/dsl.hpp"
#include "caf/config_option_set.hpp" #include "caf/config_option_set.hpp"
#include "caf/settings.hpp"
using std::string; using std::string;
using std::vector; using std::vector;
...@@ -75,7 +76,7 @@ CAF_TEST(parse with ref syncing) { ...@@ -75,7 +76,7 @@ CAF_TEST(parse with ref syncing) {
.add<string>(bar_s, "bar", "s,s", "") .add<string>(bar_s, "bar", "s,s", "")
.add<vector<string>>(bar_l, "bar", "l,l", "") .add<vector<string>>(bar_l, "bar", "l,l", "")
.add<dictionary<string>>(bar_d, "bar", "d,d", ""); .add<dictionary<string>>(bar_d, "bar", "d,d", "");
dictionary<config_value::dictionary> cfg; settings cfg;
vector<string> args{"-i42", vector<string> args{"-i42",
"-f", "-f",
"1e12", "1e12",
...@@ -103,7 +104,7 @@ CAF_TEST(parse with ref syncing) { ...@@ -103,7 +104,7 @@ CAF_TEST(parse with ref syncing) {
CAF_TEST(implicit global) { CAF_TEST(implicit global) {
opts.add<int>("value", "some value").add<bool>("help", "print help text"); opts.add<int>("value", "some value").add<bool>("help", "print help text");
CAF_MESSAGE("test long option with argument"); CAF_MESSAGE("test long option with argument");
dictionary<config_value::dictionary> cfg; settings cfg;
auto res = opts.parse(cfg, {"--value=42"}); auto res = opts.parse(cfg, {"--value=42"});
CAF_CHECK_EQUAL(res.first, pec::success); CAF_CHECK_EQUAL(res.first, pec::success);
CAF_CHECK_EQUAL(get_if<int>(&cfg, "global.value"), 42); CAF_CHECK_EQUAL(get_if<int>(&cfg, "global.value"), 42);
...@@ -118,7 +119,7 @@ CAF_TEST(atom parameters) { ...@@ -118,7 +119,7 @@ CAF_TEST(atom parameters) {
opts.add<atom_value>("value,v", "some value"); opts.add<atom_value>("value,v", "some value");
CAF_MESSAGE("test atom option without quotes"); CAF_MESSAGE("test atom option without quotes");
auto parse_args = [&](std::vector<std::string> args) -> expected<atom_value> { auto parse_args = [&](std::vector<std::string> args) -> expected<atom_value> {
dictionary<config_value::dictionary> cfg; settings cfg;
auto res = opts.parse(cfg, std::move(args)); auto res = opts.parse(cfg, std::move(args));
if (res.first != pec::success) if (res.first != pec::success)
return res.first; return res.first;
......
...@@ -250,17 +250,3 @@ CAF_TEST(unsuccessful parsing) { ...@@ -250,17 +250,3 @@ CAF_TEST(unsuccessful parsing) {
CAF_CHECK_EQUAL(parse("{a=1,"), pec::unexpected_eof); CAF_CHECK_EQUAL(parse("{a=1,"), pec::unexpected_eof);
CAF_CHECK_EQUAL(parse("{a=1 b=2}"), pec::unexpected_character); CAF_CHECK_EQUAL(parse("{a=1 b=2}"), pec::unexpected_character);
} }
CAF_TEST(put values) {
using v = config_value;
using d = config_value::dictionary;
using dd = caf::dictionary<d>;
dd content;
put(content, "a.b", 42);
CAF_CHECK_EQUAL(content, dd({{"a", d({{"b", v{42}}})}}));
put(content, "a.b.c", 1);
CAF_CHECK_EQUAL(content, dd({{"a", d({{"b", v{d({{"c", v{1}}})}}})}}));
put(content, "a.b.d", 2);
CAF_CHECK_EQUAL(content,
dd({{"a", d({{"b", v{d({{"c", v{1}}, {"d", v{2}}})}}})}}));
}
...@@ -48,7 +48,7 @@ impl = 'foo';some atom ...@@ -48,7 +48,7 @@ impl = 'foo';some atom
struct fixture { struct fixture {
detail::parser::state<std::string::const_iterator> res; detail::parser::state<std::string::const_iterator> res;
config_option_set options; config_option_set options;
config_option_set::config_map config; settings config;
fixture() { fixture() {
options.add<bool>("global", "is_server", "enables server mode") options.add<bool>("global", "is_server", "enables server mode")
......
...@@ -532,9 +532,16 @@ struct fixture { ...@@ -532,9 +532,16 @@ struct fixture {
return *static_cast<entity*>(actor_cast<abstract_actor*>(hdl)); return *static_cast<entity*>(actor_cast<abstract_actor*>(hdl));
} }
static actor_system_config& init_config(actor_system_config& cfg) {
if (auto err = cfg.parse(caf::test::engine::argc(),
caf::test::engine::argv()))
CAF_FAIL("parsing the config failed: " << to_string(err));
cfg.set("scheduler.policy", caf::atom("testing"));
return cfg;
}
fixture() fixture()
: sys(cfg.parse(caf::test::engine::argc(), caf::test::engine::argv()) : sys(init_config(cfg)),
.set("scheduler.policy", caf::atom("testing"))),
sched(dynamic_cast<scheduler_type&>(sys.scheduler())), sched(dynamic_cast<scheduler_type&>(sys.scheduler())),
alice_hdl(spawn(sys, 0, "alice", tc)), alice_hdl(spawn(sys, 0, "alice", tc)),
bob_hdl(spawn(sys, 1, "bob", tc)), bob_hdl(spawn(sys, 1, "bob", tc)),
......
...@@ -41,10 +41,7 @@ struct dummy_thread_hook : thread_hook { ...@@ -41,10 +41,7 @@ struct dummy_thread_hook : thread_hook {
} }
void thread_started() override { void thread_started() override {
void* array[20]; \ // nop
auto caf_bt_size = ::backtrace(array, 20); \
std::unique_lock<std::mutex> guard{mx};
::backtrace_symbols_fd(array, caf_bt_size, 2); \
} }
void thread_terminates() override { void thread_terminates() override {
......
...@@ -20,9 +20,10 @@ ...@@ -20,9 +20,10 @@
#include <algorithm> #include <algorithm>
#include "caf/logger.hpp" #include "caf/actor_system_config.hpp"
#include "caf/defaults.hpp"
#include "caf/config_value.hpp" #include "caf/config_value.hpp"
#include "caf/defaults.hpp"
#include "caf/logger.hpp"
#include "caf/io/network/default_multiplexer.hpp" #include "caf/io/network/default_multiplexer.hpp"
......
...@@ -20,11 +20,11 @@ ...@@ -20,11 +20,11 @@
#include <algorithm> #include <algorithm>
#include "caf/logger.hpp" #include "caf/actor_system_config.hpp"
#include "caf/defaults.hpp"
#include "caf/config_value.hpp" #include "caf/config_value.hpp"
#include "caf/defaults.hpp"
#include "caf/io/network/default_multiplexer.hpp" #include "caf/io/network/default_multiplexer.hpp"
#include "caf/logger.hpp"
namespace caf { namespace caf {
namespace io { namespace io {
......
...@@ -148,7 +148,10 @@ behavior peer_acceptor_fun(broker* self, const actor& buddy) { ...@@ -148,7 +148,10 @@ behavior peer_acceptor_fun(broker* self, const actor& buddy) {
void run_client(int argc, char** argv, uint16_t port) { void run_client(int argc, char** argv, uint16_t port) {
actor_system_config cfg; actor_system_config cfg;
actor_system system{cfg.load<io::middleman>().parse(argc, argv)}; cfg.load<io::middleman>();
if (auto err = cfg.parse(argc, argv))
CAF_FAIL("failed to parse config: " << to_string(err));
actor_system system{cfg};
auto p = system.spawn(ping, size_t{10}); auto p = system.spawn(ping, size_t{10});
CAF_MESSAGE("spawn_client..."); CAF_MESSAGE("spawn_client...");
auto cl = unbox(system.middleman().spawn_client(peer_fun, auto cl = unbox(system.middleman().spawn_client(peer_fun,
...@@ -160,7 +163,10 @@ void run_client(int argc, char** argv, uint16_t port) { ...@@ -160,7 +163,10 @@ void run_client(int argc, char** argv, uint16_t port) {
void run_server(int argc, char** argv) { void run_server(int argc, char** argv) {
actor_system_config cfg; actor_system_config cfg;
actor_system system{cfg.load<io::middleman>().parse(argc, argv)}; cfg.load<io::middleman>();
if (auto err = cfg.parse(argc, argv))
CAF_FAIL("failed to parse config: " << to_string(err));
actor_system system{cfg};
scoped_actor self{system}; scoped_actor self{system};
CAF_MESSAGE("spawn peer acceptor"); CAF_MESSAGE("spawn peer acceptor");
auto serv = system.middleman().spawn_broker(peer_acceptor_fun, auto serv = system.middleman().spawn_broker(peer_acceptor_fun,
......
...@@ -40,6 +40,8 @@ public: ...@@ -40,6 +40,8 @@ public:
config() { config() {
load<io::middleman>(); load<io::middleman>();
add_message_type<std::vector<int>>("std::vector<int>"); add_message_type<std::vector<int>>("std::vector<int>");
if (auto err = parse(test::engine::argc(), test::engine::argv()))
CAF_FAIL("failed to parse config: " << to_string(err));
} }
}; };
...@@ -55,11 +57,9 @@ struct fixture { ...@@ -55,11 +57,9 @@ struct fixture {
io::middleman& client_side_mm; io::middleman& client_side_mm;
fixture() fixture()
: server_side(server_side_config.parse(test::engine::argc(), : server_side(server_side_config),
test::engine::argv())),
server_side_mm(server_side.middleman()), server_side_mm(server_side.middleman()),
client_side(client_side_config.parse(test::engine::argc(), client_side(client_side_config),
test::engine::argv())),
client_side_mm(client_side.middleman()) { client_side_mm(client_side.middleman()) {
// nop // nop
} }
......
...@@ -41,6 +41,8 @@ public: ...@@ -41,6 +41,8 @@ public:
load<io::middleman>(); load<io::middleman>();
set("middleman.enable-udp", true); set("middleman.enable-udp", true);
add_message_type<std::vector<int>>("std::vector<int>"); add_message_type<std::vector<int>>("std::vector<int>");
if (auto err = parse(test::engine::argc(), test::engine::argv()))
CAF_FAIL("failed to parse config: " << to_string(err));
} }
}; };
...@@ -56,11 +58,9 @@ struct fixture { ...@@ -56,11 +58,9 @@ struct fixture {
io::middleman& client_side_mm; io::middleman& client_side_mm;
fixture() fixture()
: server_side(server_side_config.parse(test::engine::argc(), : server_side(server_side_config),
test::engine::argv())),
server_side_mm(server_side.middleman()), server_side_mm(server_side.middleman()),
client_side(client_side_config.parse(test::engine::argc(), client_side(client_side_config),
test::engine::argv())),
client_side_mm(client_side.middleman()) { client_side_mm(client_side.middleman()) {
// nop // nop
} }
......
...@@ -164,7 +164,10 @@ acceptor::behavior_type acceptor_fun(acceptor::broker_pointer self, ...@@ -164,7 +164,10 @@ acceptor::behavior_type acceptor_fun(acceptor::broker_pointer self,
void run_client(int argc, char** argv, uint16_t port) { void run_client(int argc, char** argv, uint16_t port) {
actor_system_config cfg; actor_system_config cfg;
actor_system system{cfg.load<io::middleman>().parse(argc, argv)}; cfg.load<io::middleman>();
if (auto err = cfg.parse(argc, argv))
CAF_FAIL("failed to parse config: " << to_string(err));
actor_system system{cfg};
auto p = system.spawn(ping, size_t{10}); auto p = system.spawn(ping, size_t{10});
CAF_MESSAGE("spawn_client_typed..."); CAF_MESSAGE("spawn_client_typed...");
auto cl = unbox(system.middleman().spawn_client(peer_fun, auto cl = unbox(system.middleman().spawn_client(peer_fun,
...@@ -176,7 +179,10 @@ void run_client(int argc, char** argv, uint16_t port) { ...@@ -176,7 +179,10 @@ void run_client(int argc, char** argv, uint16_t port) {
void run_server(int argc, char** argv) { void run_server(int argc, char** argv) {
actor_system_config cfg; actor_system_config cfg;
actor_system system{cfg.load<io::middleman>().parse(argc, argv)}; cfg.load<io::middleman>();
if (auto err = cfg.parse(argc, argv))
CAF_FAIL("failed to parse config: " << to_string(err));
actor_system system{cfg};
scoped_actor self{system}; scoped_actor self{system};
auto serv = system.middleman().spawn_broker(acceptor_fun, system.spawn(pong)); auto serv = system.middleman().spawn_broker(acceptor_fun, system.spawn(pong));
std::thread child; std::thread child;
...@@ -199,7 +205,5 @@ void run_server(int argc, char** argv) { ...@@ -199,7 +205,5 @@ void run_server(int argc, char** argv) {
} // namespace <anonymous> } // namespace <anonymous>
CAF_TEST(test_typed_broker) { CAF_TEST(test_typed_broker) {
auto argc = test::engine::argc(); run_server(test::engine::argc(), test::engine::argv());
auto argv = test::engine::argv();
run_server(argc, argv);
} }
...@@ -77,8 +77,9 @@ void run_client(int argc, char** argv, uint16_t port) { ...@@ -77,8 +77,9 @@ void run_client(int argc, char** argv, uint16_t port) {
actor_system_config cfg; actor_system_config cfg;
cfg.load<io::middleman>() cfg.load<io::middleman>()
.add_message_type<ping>("ping") .add_message_type<ping>("ping")
.add_message_type<pong>("pong") .add_message_type<pong>("pong");
.parse(argc, argv); if (auto err = cfg.parse(argc, argv))
CAF_FAIL("failed to parse config: " << to_string(err));
actor_system sys{cfg}; actor_system sys{cfg};
// check whether invalid_argument is thrown // check whether invalid_argument is thrown
// when trying to connect to get an untyped // when trying to connect to get an untyped
......
...@@ -53,11 +53,17 @@ public: ...@@ -53,11 +53,17 @@ public:
} }
}; };
struct config : actor_system_config {
config() {
load<io::middleman>();
if (auto err = parse(test::engine::argc(), test::engine::argv()))
CAF_FAIL("failed to parse config: " << to_string(err));
}
};
struct fixture { struct fixture {
fixture() { fixture() {
new (&system) actor_system(cfg.load<io::middleman>() new (&system) actor_system(cfg);
.parse(test::engine::argc(),
test::engine::argv()));
testee = system.spawn<dummy>(); testee = system.spawn<dummy>();
} }
...@@ -90,7 +96,7 @@ struct fixture { ...@@ -90,7 +96,7 @@ struct fixture {
return result; return result;
} }
actor_system_config cfg; config cfg;
union { actor_system system; }; // manually control ctor/dtor union { actor_system system; }; // manually control ctor/dtor
actor testee; actor testee;
}; };
......
...@@ -556,13 +556,20 @@ public: ...@@ -556,13 +556,20 @@ public:
// -- constructors, destructors, and assignment operators -------------------- // -- constructors, destructors, and assignment operators --------------------
static Config& init_config(Config& cfg) {
if (auto err = cfg.parse(caf::test::engine::argc(),
caf::test::engine::argv()))
CAF_FAIL("failed to parse config: " << to_string(err));
cfg.set("scheduler.policy", caf::atom("testing"));
cfg.set("logger.inline-output", true);
cfg.set("middleman.network-backend", caf::atom("testing"));
return cfg;
}
template <class... Ts> template <class... Ts>
explicit test_coordinator_fixture(Ts&&... xs) explicit test_coordinator_fixture(Ts&&... xs)
: cfg(std::forward<Ts>(xs)...), : cfg(std::forward<Ts>(xs)...),
sys(cfg.parse(caf::test::engine::argc(), caf::test::engine::argv()) sys(init_config(cfg)),
.set("scheduler.policy", caf::atom("testing"))
.set("logger.inline-output", true)
.set("middleman.network-backend", caf::atom("testing"))),
self(sys, true), self(sys, true),
sched(dynamic_cast<scheduler_type&>(sys.scheduler())) { sched(dynamic_cast<scheduler_type&>(sys.scheduler())) {
// Configure the clock to measure each batch item with 1us. // Configure the clock to measure each batch item with 1us.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment