Flow-IPC 1.0.2
Flow-IPC project: Public API.
|
Implements Session concept on the Client_app end: a Session_mv that first achieves PEER state by connecting to an opposing Session_server_mv via Client_session_mv::sync_connect(). More...
#include <client_session.hpp>
Public Types | |
using | Base = Session_mv< Client_session_impl_t > |
Short-hand for our base class. To the user: note its public API is inherited. | |
Public Types inherited from ipc::session::Session_mv< Client_session_impl_t > | |
using | Channel_obj = typename Impl::Channel_obj |
Implements Session API per contract. More... | |
using | Channels = typename Impl::Channels |
Container (vector<> ) of Channel_obj. | |
using | Mdt_payload_obj = typename Impl::Mdt_payload_obj |
Implements Session API per contract. More... | |
using | Mdt_builder = typename Impl::Mdt_builder |
Implements Session API per contract. More... | |
using | Mdt_builder_ptr = typename Impl::Mdt_builder_ptr |
Implements Session API per contract. More... | |
using | Mdt_reader_ptr = typename Impl::Mdt_reader_ptr |
Implements Session API per contract. More... | |
using | Structured_channel = typename transport::struc::Channel_via_heap< Channel_obj, Message_body > |
Implements Session API per contract. More... | |
using | Structured_msg_builder_config = typename Impl::Structured_msg_builder_config |
Implements Session API per contract. More... | |
using | Structured_msg_reader_config = typename Impl::Structured_msg_builder_config |
Implements Session API per contract. More... | |
Public Member Functions | |
template<typename On_passive_open_channel_handler , typename Task_err > | |
Client_session_mv (flow::log::Logger *logger_ptr, const Client_app &cli_app_ref, const Server_app &srv_app_ref, Task_err &&on_err_func, On_passive_open_channel_handler &&on_passive_open_channel_func) | |
Constructs (passive-opens allowed form) in NULL state. More... | |
template<typename Task_err > | |
Client_session_mv (flow::log::Logger *logger_ptr, const Client_app &cli_app_ref, const Server_app &srv_app_ref, Task_err &&on_err_func) | |
Constructs (passive-opens disallowed form) in NULL state. More... | |
Mdt_builder_ptr | mdt_builder () |
Implements Session API per contract; plus usable to generate blank mdt argument for advanced sync_connect() overload. More... | |
bool | sync_connect (Error_code *err_code=0) |
To be invoked in NULL state only, and not as-if default-cted, it synchronously and non-blockingly attempts to connect to an opposing Session_server ; and synchronously reports failure or success, the latter showing *this has entered PEER state. More... | |
bool | sync_connect (const typename Base::Mdt_builder_ptr &mdt, typename Base::Channels *init_channels_by_cli_req_pre_sized=0, typename Base::Mdt_reader_ptr *mdt_from_srv_or_null=0, typename Base::Channels *init_channels_by_srv_req=0, Error_code *err_code=0) |
Identical to the simpler sync_connect() overload but offers added advanced capabilities: metadata exchange; initial-channel opening. More... | |
Public Member Functions inherited from ipc::session::Session_mv< Client_session_impl_t > | |
Session_mv () | |
Implements Session API per contract. More... | |
Session_mv (Session_mv &&src) | |
Implements Session API per contract. More... | |
Session_mv (const Session_mv &)=delete | |
Copy ction is disallowed. | |
~Session_mv () | |
Implements Session API per contract. More... | |
Session_mv & | operator= (Session_mv &&src) |
Implements Session API per contract. More... | |
Session_mv & | operator= (const Session_mv &)=delete |
Copy assignment is disallowed. | |
Mdt_builder_ptr | mdt_builder () |
Implements Session API per contract. More... | |
bool | open_channel (Channel_obj *target_channel, const Mdt_builder_ptr &mdt, Error_code *err_code=0) |
Implements Session API per contract. More... | |
bool | open_channel (Channel_obj *target_channel, Error_code *err_code=0) |
Implements Session API per contract. More... | |
const Session_token & | session_token () const |
Implements Session API per contract. More... | |
transport::struc::Heap_fixed_builder::Config | heap_fixed_builder_config () |
Utility that obtains a heap-based (non-zero-copy) Struct_builder::Config, constructed with the most efficient yet safe values, for transport::struc::Msg_out (out-messages) compatible with Structured_channel upgraded-from Channel_obj channels opened via *this Session_mv. More... | |
transport::struc::Heap_reader::Config | heap_reader_config () |
Deserializing counterpart to non-static heap_fixed_builder_config(). More... | |
flow::log::Logger * | get_logger () const |
Returns logger (possibly null). More... | |
const flow::log::Component & | get_log_component () const |
Returns log component. More... | |
Related Functions | |
(Note that these are not member functions.) | |
template<typename Client_session_impl_t > | |
std::ostream & | operator<< (std::ostream &os, const Client_session_mv< Client_session_impl_t > &val) |
Prints string representation of the given Client_session_mv to the given ostream . More... | |
Related Functions inherited from ipc::session::Session_mv< Client_session_impl_t > | |
std::ostream & | operator<< (std::ostream &os, const Session_mv< Client_session_impl_t > &val) |
Prints string representation of the given Session_mv to the given ostream . More... | |
Additional Inherited Members | |
Static Public Member Functions inherited from ipc::session::Session_mv< Client_session_impl_t > | |
static transport::struc::Heap_fixed_builder::Config | heap_fixed_builder_config (flow::log::Logger *logger_ptr) |
Utility that obtains a heap-based (non-zero-copy) Struct_builder::Config, constructed with the most efficient yet safe values, for transport::struc::Msg_out (out-messages) compatible with Structured_channel upgraded-from Channel_obj channels opened via this Session_mv type. More... | |
static transport::struc::Heap_reader::Config | heap_reader_config (flow::log::Logger *logger_ptr) |
Deserializing counterpart to static heap_fixed_builder_config(). More... | |
Static Public Attributes inherited from ipc::session::Session_mv< Client_session_impl_t > | |
static constexpr schema::ShmType | S_SHM_TYPE |
Implements Session API per contract. More... | |
static constexpr bool | S_SHM_ENABLED |
Implements Session API per contract. More... | |
static constexpr bool | S_MQS_ENABLED |
Compile-time-known constant indicating whether Channel_obj shall use a blobs pipe over message queues (MQs). | |
static constexpr bool | S_SOCKET_STREAM_ENABLED |
Compile-time-known constant indicating whether Channel_obj shall use socket stream for any type of pipe. More... | |
Protected Types inherited from ipc::session::Session_mv< Client_session_impl_t > | |
using | Impl = Client_session_impl_t |
Short-hand for pImpl-lite impl type. This shall be the deepest impl sub-class desired. | |
using | Session_base_obj = typename Impl::Session_base_obj |
Short-hand for Impl's Session_base super-class. | |
using | Impl_ptr = std::experimental::propagate_const< boost::movelib::unique_ptr< Impl > > |
Short-hand for const -respecting wrapper around Impl for the pImpl idiom. See impl(). | |
Protected Member Functions inherited from ipc::session::Session_mv< Client_session_impl_t > | |
const Session_base_obj & | base () const |
Provides const access to Session_base super-object. More... | |
Impl_ptr & | impl () |
pImpl target; particularly for sub-classes that must add to the above public API. More... | |
const Impl_ptr & | impl () const |
pImpl target; particularly for sub-classes that must add to the above public API. More... | |
Implements Session concept on the Client_app end: a Session_mv that first achieves PEER state by connecting to an opposing Session_server_mv via Client_session_mv::sync_connect().
See overview of Session hierarchy in namespace ipc::session doc header; then come back here if desired.
It is unusual to use Client_session_mv template directly. If you do wish to set up a client-side session peer, and you do not require SHM support, then use Client_session alias template. The client-specific API, particularly ctor and sync_connect(), is in Client_session_mv and documented here. The side-agnostic API – active once PEER state is achieved – is described by Session (concept) doc header and implemented concretely by Session_mv which is our public
, non-virtual
super-class.
If you do wish to set up a client-side session peer, but you do require SHM support, then use shm::classic::Client_session or similar (for other SHM-provider(s)). However Client_session (hence Client_session_mv to which it aliases) is its super-class, and until PEER state is reached its API remains the only relevant API to use. Once Client_session_mv::sync_connect() puts *this
into PEER state, super-class Session_mv (= Session concept) API continues to be relevant. Also in PEER state SHM-relevant additional API members (e.g., shm::classic::Session_mv::app_shm()`) become of interest.
Summary hierarchy:
session_shm()
...; suitable for transport::struc::Channel_base::Serialize_via_session_shm)We may refer to Client_session_mv as Client_session below; particularly since it is likeliest used in that form by the user.
Per the Session concept a Client_session is open/capable of operation when in PEER state only. A Client_session object is always in one of 2 states:
To get from NULL state to PEER state: Use Session_server on the other side. On this side construct a Client_session (always in NULL state) and invoke sync_connect() which will synchronously and non-blockingly try to move to PEER state (mission accomplished). If the connect fails, it will stay in NULL state. Being moved-from makes a *this
as-if default-cted; therefore also moves to NULL state.
Once in PEER state Client_session simply follows Session concept semantics. At this stage our super-class Session_mv implements that concept in particular. See either doc header (Session, Session_mv).
A related reminder:
async_accept()
or both may optionally specify that 1+ init-channels be opened before this and the opposing Session is in PEER state and emitted to user. This may be a sufficient replacement of, or complementary to, active-open/passive-open APIs available once the Session is in PEER state/emitted to user. If not sufficient:Without networking, the other side (Session_server) either exists/is listening; or no. Connecting is a synchronous, non-blocking operation; so an async_connect()
API in this context only makes life harder for the user. (However, there are some serious plans to add a networking-capable counterpart (probably via TCP at least) to Native_socket_stream
and therefore Client_session_mv; such a networky-client-session class will almost certainly have an async_connect()
, while its sync_connect()
will probably become potentially blocking.)
*this
becomes network-enabled, open_channel() too will need an async form most likely, while existing open_channel() would become potentially-blocking.These follow the Session concept policies.
Once in PEER state, error handling follows the Session concept (= Session_mv concrete class) doc header. Up to that point (in NULL state) there are no public asynchronous operations; there is just sync_connect() which succeeds or fails synchronously and quickly.
Client_session_impl_t | An implementation detail. Use one of the aliases prescribed near the top of this doc header to set this correctly. |
|
explicit |
Constructs (passive-opens allowed form) in NULL state.
To be useful, invoke sync_connect() next.
logger_ptr | Logger to use for logging subsequently. |
cli_app_ref | Properties of this client application. The address is copied; the object is not copied. |
srv_app_ref | Properties of the opposing server application. The address is copied; the object is not copied. |
on_err_func | On-error handler. See Session concept doc header for semantics. |
on_passive_open_channel_func | On-passive-open handler. See Session concept doc header for semantics. |
|
explicit |
Constructs (passive-opens disallowed form) in NULL state.
To be useful, invoke sync_connect() next.
logger_ptr | Logger to use for logging subsequently. |
cli_app_ref | Properties of this client application. The address is copied; the object is not copied. |
srv_app_ref | Properties of the opposing server application. The address is copied; the object is not copied. |
on_err_func | On-error handler. See Session concept doc header for semantics. |
Task_err | See Session concept doc header for semantics. |
Mdt_builder_ptr ipc::session::Client_session_mv< Client_session_impl_t >::mdt_builder | ( | ) |
Implements Session API per contract; plus usable to generate blank mdt
argument for advanced sync_connect() overload.
That is: can additionally be invoked in NULL state (before sync_connect() or between a failed attempt and the next attempt). The return value can be used only as follows; otherwise undefined behavior results:
bool ipc::session::Client_session_mv< Client_session_impl_t >::sync_connect | ( | const typename Base::Mdt_builder_ptr & | mdt, |
typename Base::Channels * | init_channels_by_cli_req_pre_sized = 0 , |
||
typename Base::Mdt_reader_ptr * | mdt_from_srv_or_null = 0 , |
||
typename Base::Channels * | init_channels_by_srv_req = 0 , |
||
Error_code * | err_code = 0 |
||
) |
Identical to the simpler sync_connect() overload but offers added advanced capabilities: metadata exchange; initial-channel opening.
The other overload is identical to sync_connect(mdt_builder(), nullptr, nullptr, nullptr, err_code)
and requires the opposing async_accept()
to similarly not use the corresponding features.
Client may wish to provide information in some way, but without a structured channel – or any channel – yet available, this provides an opportunity to do so in a structured way with a one-off message available at session open, together with the opposing Session object itself.
Similarly to how it is optionally done on a per-channel-open basis (open_channel()): call mdt = mdt_builder()
; fill out the resulting capnp structure *mdt
; then pass mdt
to sync_connect(). Opposing async_accept()
shall receive deserializable Mdt_reader
together with the freshly-opened Session, though they may choose to ignore it.
To omit using this feature, skip the "fill out the resulting capnp structure" step. You must still call mdt_builder() and pass-in the result. (The other overload does so.)
This is the reverse of the above. Whatever the opposing server chose to supply as server->client metadata shall be deserializable at *mdt_from_srv_or_null
on successful return from sync_connect()
. If mdt_from_srv_or_null
is null, the srv->cli metadata shall be ignored.
Once the session is open, open_channel() and the on-passive-open handler may be used to open channels at will. In many use cases, however, a certain number of channels is required immediately before work can really begin (and, frequently, no further channels are even needed). For convenience (to avoid asynchrony/boiler-plate) the init-channels feature will pre-open a requested # of channels making them available right away, together with the freshly-open session – to both sides.
The client may request 0 or more init-channels. They shall be opened and placed into *init_channels_by_cli_req_pre_sized
; its ->size()
at entry to the method indicates the number of channels requested. If null, it is treated as if ->size() == 0
, meaning no init-channels-by-client-request are opened.
This is the reverse of the above. The opposing side shall request 0 or more init-channels-by-server-request; that number of channels shall be opened; and they will be placed into *init_channels_by_srv_req
which shall be ->resize()
d accordingly on successful return from sync_connect()
.
init_channels_by_srv_req
being null is allowed, but only if the opposing server requests 0 init-channels-by-server-request. Otherwise an error shall be emitted (see below).
mdt | See above. |
init_channels_by_cli_req_pre_sized | See above: null or pointer to container of Channel_obj with .size() specifying how many channels this side is requesting to be opened on its behalf; each element will be move-assigned a PEER-state Channel_obj on success. Recommend simply ct-ing with (n) or .resize(n) which loads it with default-cted (NULL-state) objects to be replaced. null is treated same as .empty() . |
mdt_from_srv_or_null | See above: null or pointer to Reader of metadata which shall be set for access on success. |
init_channels_by_srv_req | See above: null or pointer to container of Channel_obj which shall be .clear() ed and replaced by a container of PEER-state Channel_obj on success the number being specified by the opposing (server) side. The number may be zero. null is allowed if and only if the number is zero; otherwise error::Code::S_INVALID_ARGUMENT is emitted. |
err_code | See other sync_connect() overload. Note the above target (pointer) args are touched only if no error is emitted via this standard Flow error reporting mechanism. |
bool ipc::session::Client_session_mv< Client_session_impl_t >::sync_connect | ( | Error_code * | err_code = 0 | ) |
To be invoked in NULL state only, and not as-if default-cted, it synchronously and non-blockingly attempts to connect to an opposing Session_server
; and synchronously reports failure or success, the latter showing *this
has entered PEER state.
Failure means *this
remains in NULL state.
If invoked outside of NULL state, or if it is as-if default-cted (i.e., default-cted or moved-from), this returns false
and otherwise does nothing.
Note that *this
(modulo moves) that has entered PEER state can never change state subsequently (even on transmission error); once a PEER, always a PEER.
While details are internal, abstractly speaking this is determined by the Server_app passed to the ctor. Internal detail (for exposition/general knowledge):
Client_session
will connect, and all other internally used cross-process resources (sockets, MQs, SHM pools...) are similarly segregated among different instances of the Server_app-described application.Server_app
s. Now it knows "where" to connect in order to open the session; so it won't accidentally connect to some old zombie instance of the Server_app (its PID wouldn't be in the CNS file any longer) or another application entirely (its PID file would be located elsewhere and never accessed by this sync_connect()).Then sync_connect() will quickly fail (file-not-found or connection-refused error). Shouldn't we supply some API to await its appearance and actively listening? Answer: Probably not. Why? Answer: Consider the situation where the PID file is there, but it belongs to a now-exited instance of the Server_app; let's say it is currently suspended or restarting. sync_connect() will fail then too: There is nothing listening (anymore) at the advertised PID. So it'll quickly fail (connection-refused error). So then we'd also need an API to await an active server's appearance whether or not the PID exists. That leads to the following to-do:
false
if and only if invoked outside of NULL state; or if *this
is as-if default-cted.err_code | See flow::Error_code docs for error reporting semantics. Error_code generated: session::error::Code::S_OBJECT_SHUTDOWN_ABORTED_COMPLETION_HANDLER (destructor called, canceling all pending ops; spiritually identical to boost::asio::error::operation_aborted ), interprocess-mutex-related errors (probably from boost.interprocess) w/r/t reading the CNS (PID file), file-related system errors w/r/t reading the CNS (PID file) (see Session_server doc header for background), error::Code::S_CLIENT_NAMESPACE_STORE_BAD_FORMAT (bad CNS contents), those emitted by transport::Native_socket_stream::sync_connect(), those emitted by transport::struc::Channel::send(), those emitted by transport::struc::Channel via on-error handler (most likely transport::error::Code::S_RECEIVES_FINISHED_CANNOT_RECEIVE indicating graceful shutdown of opposing process coincidentally during log-in procedure, prematurely ending session while it was starting), error::Code::S_CLIENT_MASTER_LOG_IN_RESPONSE_BAD, error::Code::S_INVALID_ARGUMENT (other side expected other sync_connect() overload with non-null init_channels_by_srv_req arg). |
|
related |
Prints string representation of the given Client_session_mv
to the given ostream
.
os | Stream to which to write. |
val | Object to serialize. |
os
.