Flow 1.0.2
Flow project: Full implementation reference.
Public Types | Public Member Functions | Public Attributes | Static Private Member Functions | Friends | List of all members
flow::net_flow::Node_options Struct Reference

A set of low-level options affecting a single Flow Node, including Peer_socket objects and other objects subsequently generated by that Flow Node. More...

#include <options.hpp>

Collaboration diagram for flow::net_flow::Node_options:
[legend]

Public Types

using Options_description = Peer_socket_options::Options_description
 Short-hand for boost.program_options config options description. See setup_config_parsing(). More...
 
using Fine_duration = Peer_socket_options::Fine_duration
 A time duration, with fine precision. More...
 

Public Member Functions

 Node_options ()
 Constructs a Node_options with values equal to those used by Node when the Node creator chooses not to supply custom options. More...
 
void setup_config_parsing (Options_description *opts_desc)
 Modifies a boost.program_options options description object to enable subsequent parsing of a command line or config file into the data members of this object, as well printing a help message about these options to an ostream. More...
 

Public Attributes

bool m_st_capture_interrupt_signals_internally
 If and only if this is true, the Node will detect SIGINT and SIGTERM (or your OS's version thereof); upon seeing such a signal, it will fire Node::interrupt_all_waits(), which will interrupt all blocking operations, conceptually similarly to POSIX's EINTR. More...
 
size_t m_st_low_lvl_max_buf_size
 The max size to ask the OS to set our UDP socket's receive buffer to in order to minimize loss if we can't process datagrams fast enough. More...
 
Fine_duration m_st_timer_min_period
 A time period such that the boost.asio timer implementation for this platform is able to accurately able to schedule events within this time period or greater. More...
 
unsigned int m_dyn_max_packets_per_main_loop_iteration
 The UDP net-stack may deliver 2 or more datagrams to the Flow Node at the same time. More...
 
size_t m_dyn_low_lvl_max_packet_size
 Any incoming low-level (UDP) packet will be truncated to this size. More...
 
bool m_dyn_guarantee_one_low_lvl_in_buf_per_socket
 This very inside-baseball setting controls the allocation/copy behavior of the UDP receive-deserialize operation sequence. More...
 
Peer_socket_options m_dyn_sock_opts
 The set of per-Peer_socket options in this per-Node set of options. More...
 

Static Private Member Functions

static std::string opt_id_to_str (const std::string &opt_id)
 Helper that, for a given option m_blah, takes something like "m_blah_blah" and returns the similar more suitable option name the user can use in a config file or command line. More...
 
template<typename Opt_type >
static void add_config_option (Options_description *opts_desc, const std::string &opt_id, Opt_type *target_val, const Opt_type &default_val, const char *description, bool printout_only)
 A helper that adds a single option to a given Options_description, for use either in printing out the current state of a Node_options or Peer_socket_options; or for parsing of config into such an object. More...
 
static void setup_config_parsing_helper (Options_description *opts_desc, Node_options *target, const Node_options &defaults_source, bool printout_only)
 Loads the full set of boost.program_options config options into the given Options_description, either for the full help message and parsing config into a Node_options, or for purposes of printout of the state of an existing Node_options object (e.g., when printing Node_options to an ostream). More...
 

Friends

struct Peer_socket_options
 The two structs work together (since Peer_socket_options needs add_config_option()). More...
 
class Node
 Node needs opt_id_to_str(). More...
 
std::ostream & operator<< (std::ostream &os, const Node_options &opts)
 Prints the name of each option in the given Node_options, along with its current value, to the given ostream. More...
 

Detailed Description

A set of low-level options affecting a single Flow Node, including Peer_socket objects and other objects subsequently generated by that Flow Node.

Typically these values can be left at defaults, and thus the net_flow user normally need not deal with these objects. However, if low-level tuning of Flow internals is needed, you can use this struct.

This is just a simple struct with a couple of utilities to serialize (to ostream) and deserialize (from a config file or command line) the values in the struct; it is not connected to any other object (for example, it can exist with no Node).

You may read from and write to members of this struct at will, and no checking will be performed; moreover, doing so will have no effect other than the field being read or written.

Fields are validated and potentially take effect, however, when you pass a Node_options object to Node. Node always copies the given Node_options and never saves a reference to it. All of that applies equally to Peer_socket_options.

Node_options contains a Peer_socket_options m_dyn_sock_opts (a very similar, in spirit, struct) within it. Options stored within that are per-flow::net_flow::Peer_socket options. For example, m_st_low_lvl_max_buf_size applies to the entire Node at all times and is stored directly in *this (as there is only one UDP buffer for the entire Node); whereas max-block-size can be different for each individual Peer_socket and is thus stored in this->m_dyn_sock_opts. See Node::listen() and Node::connect() for how per-socket options are distributed to subsequent sockets as connections are made.

The struct, when default-constructed, contains sane default values as used by Node when not provided with a Node_options object. Alternatively, you can get a Node's existing set of options via Node::options().

After obtaining a Node_options either way, you may assign values to it manually.

Alternatively, you can fill it parsing a config file or command line using boost.program_options (which makes it a snap) with the help of Node_options::setup_config_parsing(), which will provide a program_options-suitable Options_description object to enable this parsing. You may conversely print Options_description to an ostream (e.g., cout) for full help text on the meaning of each option and the defaults.

You may also print a filled Node_options itself to an ostream for the current settings stored in that object.

Thready safety

Same as any struct with no locking done therein.

See also
Node constructor, Node::set_options(), Node::listen(), Node::connect().
Peer_socket::set_options(), Peer_socket::options().
Peer_socket_options.

If you want to add an option, follow these steps:

  1. Decide whether it's a per-socket or per-Node option (usually the former) and add it to Peer_socket_options or Node_options, respectively, using the below steps.
  2. Decide whether the option's value may be changed after the enclosing Node_options or Peer_socket_options has been accepted by a running Node or Peer_socket, respectively. Most options tend to be static (cannot be changed once a Node or Peer_socket has accepted them). Based on this, the data member must start with m_st_ (static) or m_dyn_ (dynamic). Choose the rest of the member name as well.
  3. Add the data member into the chosen struct. Fully comment the meaning, as for other present options.
  4. Add an ADD_CONFIG_OPTION() line into the proper struct setup_config_parsing_helper() by analogy with other present options. The description string should usually be a copy of the comment from step 3.
  5. Add the default value (very important) into the the proper struct constructor. Explain the choice of default with a comment.
  6. Is this a static option (step 2)? If so, add static validation (by analogy with present options) to Node::validate_options() or Node::sock_validate_options().
  7. Add semantic validation (such as for illegal values, including illegal values due to inconsistency with other option values) to Node::validate_options() or Node::sock_validate_options(). For some options all values are legal, in which case you needn't add anything.
  8. Use the option. EVERY read of the option should be performed through Node::opt() or Peer_socket::opt(), for thread safety. The only exception is if you manually lock Node::m_opt_mutex or Peer_socket::m_opt_mutex, respectively.

Definition at line 448 of file options.hpp.

Member Typedef Documentation

◆ Fine_duration

A time duration, with fine precision.

Definition at line 456 of file options.hpp.

◆ Options_description

Short-hand for boost.program_options config options description. See setup_config_parsing().

Definition at line 453 of file options.hpp.

Constructor & Destructor Documentation

◆ Node_options()

flow::net_flow::Node_options::Node_options ( )
explicit

Constructs a Node_options with values equal to those used by Node when the Node creator chooses not to supply custom options.

Definition at line 41 of file options.cpp.

Member Function Documentation

◆ add_config_option()

template<typename Opt_type >
void flow::net_flow::Node_options::add_config_option ( Options_description opts_desc,
const std::string &  opt_id,
Opt_type *  target_val,
const Opt_type &  default_val,
const char *  description,
bool  printout_only 
)
staticprivate

A helper that adds a single option to a given Options_description, for use either in printing out the current state of a Node_options or Peer_socket_options; or for parsing of config into such an object.

Template Parameters
Opt_typeThe type of a data member of of Node_options or Peer_socket_options.
Parameters
opts_descThe Options_description object into which to load a single option_description.
opt_idA string whose content equals the name (in C++ code) of a data member of Node_options or Peer_socket_options (presumably generated using the macro hash technique).
target_valIf !printout_only, and the user parses via *opts_desc, the parsed option value will be loaded into *target_val. Otherwise ignored.
default_valThe default value to this option in *opts_desc will be this.
descriptionIf !printout_only, the detailed description of the option will be this. Otherwise ignored.
printout_onlySee above.

Definition at line 61 of file options.cpp.

References opt_id_to_str().

Here is the call graph for this function:

◆ opt_id_to_str()

std::string flow::net_flow::Node_options::opt_id_to_str ( const std::string &  opt_id)
staticprivate

Helper that, for a given option m_blah, takes something like "m_blah_blah" and returns the similar more suitable option name the user can use in a config file or command line.

For example, "m_st_max_block_size" yields "max-block-size".

Parameters
opt_idA string whose content equals the name (in C++ code) of a data member of Node_options or Peer_socket_options (presumably generated using the macro hash technique).
Returns
See above.

Definition at line 160 of file options.cpp.

Referenced by add_config_option(), and flow::net_flow::Node::validate_static_option().

Here is the caller graph for this function:

◆ setup_config_parsing()

void flow::net_flow::Node_options::setup_config_parsing ( Options_description opts_desc)

Modifies a boost.program_options options description object to enable subsequent parsing of a command line or config file into the data members of this object, as well printing a help message about these options to an ostream.

In particular, after executing this method:

  • If you output *opts_desc to an ostream, the ostream will get a detailed description of each option, its symbolic name (for config file or command line), and its value if the config file or command line omits this option (the default). This default will equal to the value of that particular option in a default-constructed Node_options.
  • If you perform something like the following code snippet, then *this will now be filled with values parsed from ifstream F (and default values for any omitted values):
namespace opts = boost::program_options;
Node_options flow_opts;
opts::options_description opts_desc;
std::ifstream F(...);
flow_opts.setup_config_parsing(&opts_desc);
opts::variables_map cfg_vars;
opts::store(opts::parse_config_file(F, *opts_desc), cfg_vars);
opts::notify(cfg_vars);
A set of low-level options affecting a single Flow Node, including Peer_socket objects and other obje...
Definition: options.hpp:449
void setup_config_parsing(Options_description *opts_desc)
Modifies a boost.program_options options description object to enable subsequent parsing of a command...
Definition: options.cpp:146

Note the default values will come from the current values inside *this.

Parameters
opts_descThe Options_description object into which to load the help information, defaults, and mapping to members of *this.

Definition at line 146 of file options.cpp.

References setup_config_parsing_helper().

Here is the call graph for this function:

◆ setup_config_parsing_helper()

void flow::net_flow::Node_options::setup_config_parsing_helper ( Options_description opts_desc,
Node_options target,
const Node_options defaults_source,
bool  printout_only 
)
staticprivate

Loads the full set of boost.program_options config options into the given Options_description, either for the full help message and parsing config into a Node_options, or for purposes of printout of the state of an existing Node_options object (e.g., when printing Node_options to an ostream).

printout_only case

Will generate an Options_description with "defaults" set to values from a defaults_source object (which should be the object you're trying to output to a stream), the names of each option, no detailed option description, and no target for each value should the caller try to actually parse using *opts_desc (which he should not). This is great when printing the current contents of a given Node_options (it just reuses the boost.program_options machinery for this purpose).

!printout_only case

Will generate an Options_description with "defaults" set to values from a defaults_source object (which should be a default-constructed Node_options), the names of each option, detailed option descriptions, and each option's target inside *target, should the caller actually parse using *opts_desc. This is useful for parsing the options set from a config file or command line.

This is the main specification for the different possible options.

Parameters
opts_descThe Options_description object to load.
targetIf !printout_only, and the user parses using *opts_desc, the parsed values will end up in members of *target.
defaults_sourceThe defaults listed (and used, if !printout_only, and you choose to parse using *opts_desc) for each option.
printout_onlySee above.

Definition at line 80 of file options.cpp.

References m_dyn_guarantee_one_low_lvl_in_buf_per_socket, m_dyn_low_lvl_max_packet_size, m_dyn_max_packets_per_main_loop_iteration, m_dyn_sock_opts, m_st_capture_interrupt_signals_internally, m_st_low_lvl_max_buf_size, m_st_timer_min_period, and flow::net_flow::Peer_socket_options::setup_config_parsing_helper().

Referenced by setup_config_parsing().

Here is the call graph for this function:
Here is the caller graph for this function:

Friends And Related Function Documentation

◆ Node

friend class Node
friend

Node needs opt_id_to_str().

See also
Node.

Definition at line 594 of file options.hpp.

◆ operator<<

std::ostream & operator<< ( std::ostream &  os,
const Node_options opts 
)
friend

Prints the name of each option in the given Node_options, along with its current value, to the given ostream.

Parameters
osStream to which to serialize.
optsObject to serialize.
Returns
os.

Definition at line 152 of file options.cpp.

◆ Peer_socket_options

friend struct Peer_socket_options
friend

The two structs work together (since Peer_socket_options needs add_config_option()).

See also
Peer_socket_options.

Definition at line 589 of file options.hpp.

Member Data Documentation

◆ m_dyn_guarantee_one_low_lvl_in_buf_per_socket

bool flow::net_flow::Node_options::m_dyn_guarantee_one_low_lvl_in_buf_per_socket

This very inside-baseball setting controls the allocation/copy behavior of the UDP receive-deserialize operation sequence.

When enabled, there is exactly one input buffer large enough to hold any one serialized incoming packet; any deserialized data (including DATA and ACK payloads) are stored in separately allocated per-packet buffers; and and the input buffer is repeatedly reused without reallocation. When disabled, however, at least some packet types (most notably DATA) will use the zero-copy principle, having the deserializer take ownership of the input buffer and access pieces inside it as post-deserialization values (most notably the DATA payload); in this case the input buffer has to be reallocated between UDP reads. As of this writing the former behavior seems to be somewhat faster, especially if low-lvl-max-packet-size is unnecessarily large; but arguably the zero-copy behavior may become faster if some implementation details related to this change. So this switch seemed worth keeping.

Definition at line 568 of file options.hpp.

Referenced by flow::net_flow::Node::handle_incoming(), and setup_config_parsing_helper().

◆ m_dyn_low_lvl_max_packet_size

size_t flow::net_flow::Node_options::m_dyn_low_lvl_max_packet_size

Any incoming low-level (UDP) packet will be truncated to this size.

This should be well above per-socket max-block-size (# of bytes of user payload per DATA packet). There will only be one buffer of this size in memory at a time, so no need to be too stingy, but on the other hand certain allocation/deallocation behavior may cause performance drops if this unnecessarily large.

Definition at line 553 of file options.hpp.

Referenced by flow::net_flow::Node::async_low_lvl_packet_send_impl(), flow::net_flow::Node::low_lvl_recv_and_handle(), setup_config_parsing_helper(), flow::net_flow::Node::sync_sock_low_lvl_rst_send(), and flow::net_flow::Node::validate_options().

◆ m_dyn_max_packets_per_main_loop_iteration

unsigned int flow::net_flow::Node_options::m_dyn_max_packets_per_main_loop_iteration

The UDP net-stack may deliver 2 or more datagrams to the Flow Node at the same time.

To lower overhead and increase efficiency, Flow will process all such datagrams – and any more that may arrive during this processing – before preparing any resulting outgoing messages, such as acknowledgments or more data packets. In high-speed conditions this may result in excessive burstiness of outgoing traffic. This option's value places a limit on the number of datagrams to process before constructing and sending any resulting outgoing messages to prevent this burstiness. If 0, there is no limit.

Definition at line 545 of file options.hpp.

Referenced by flow::net_flow::Node::low_lvl_recv_and_handle(), and setup_config_parsing_helper().

◆ m_dyn_sock_opts

Peer_socket_options flow::net_flow::Node_options::m_dyn_sock_opts

The set of per-Peer_socket options in this per-Node set of options.

This represents the per-socket options each subsequent socket generated in the corresponding Node will get, unless user specifies a custom set of such options.

Note that, in the context of the per-Node options set, this is dynamic; any per-socket option (even a static one) must be changeable in the global per-Node options set, as otherwise it would just be a regular per-Node data member in Node_options, as it could never change anyway, so no point in having it be per-Peer_socket.

Definition at line 580 of file options.hpp.

Referenced by flow::net_flow::Node::handle_syn_to_listening_server(), flow::net_flow::Node::max_block_size(), setup_config_parsing_helper(), and flow::net_flow::Node::validate_options().

◆ m_st_capture_interrupt_signals_internally

bool flow::net_flow::Node_options::m_st_capture_interrupt_signals_internally

If and only if this is true, the Node will detect SIGINT and SIGTERM (or your OS's version thereof); upon seeing such a signal, it will fire Node::interrupt_all_waits(), which will interrupt all blocking operations, conceptually similarly to POSIX's EINTR.

If this is true, the user may register their own signal handler(s) (for any purpose whatsoever) using boost::asio::signal_set. However, behavior is undefined if the program registers signal handlers via any other API, such as sigaction() or signal(). If you need to set up such a non-signal_set signal handler, AND you require EINTR-like behavior, then (1) set this option to false; (2) trap SIGINT and SIGTERM yourself; (3) in your handlers for the latter, simply call Node::interrupt_all_waits(). Similarly, if you want custom behavior regarding Node::interrupt_all_waits(), feel free to call it whenever you want (not necessarily even from a signal handler), and set this to false. However, if a typical, common-sense behavior is what you're after – and either don't need additional signal handling or are OK with using signal_set for it – then setting this to true is a good option.

Definition at line 517 of file options.hpp.

Referenced by setup_config_parsing_helper(), and flow::net_flow::Node::worker_run().

◆ m_st_low_lvl_max_buf_size

size_t flow::net_flow::Node_options::m_st_low_lvl_max_buf_size

The max size to ask the OS to set our UDP socket's receive buffer to in order to minimize loss if we can't process datagrams fast enough.

This should be as high as possible while being "acceptable" in terms of memory. However, the OS will probably have its own limit and may well pick a limit that is the minimum of that limit and this value.

Definition at line 525 of file options.hpp.

Referenced by setup_config_parsing_helper(), flow::net_flow::Node::validate_options(), and flow::net_flow::Node::worker_run().

◆ m_st_timer_min_period

Fine_duration flow::net_flow::Node_options::m_st_timer_min_period

A time period such that the boost.asio timer implementation for this platform is able to accurately able to schedule events within this time period or greater.

If you select 0, the code will decide what this value is based on the platform, but its logic for this may or may not be correct (actually it will probably be correct but possibly too conservative [large], causing timer coarseness in mechanisms like the rather critical packet pacing).

Definition at line 534 of file options.hpp.

Referenced by setup_config_parsing_helper(), flow::net_flow::Node::sock_pacing_new_time_slice(), and flow::net_flow::Node::validate_options().


The documentation for this struct was generated from the following files: