Flow-IPC 3.0.0
Flow-IPC project: Full implementation reference.
Public Types | Public Attributes | Related Functions | List of all members
ipc::session::App Struct Reference

A description of an application in this ipc::session inter-process communication universe. More...

#include <app.hpp>

Inheritance diagram for ipc::session::App:
[legend]
Collaboration diagram for ipc::session::App:
[legend]

Public Types

using Master_set = boost::unordered_map< std::string, App >
 Type for storing master repository of all Apps. More...
 

Public Attributes

std::string m_name
 Brief application name, readable to humans and unique across all other applications' names; used both as a short programmatic key in shared resource naming (including as a folder in Shared_name for kernel-persistent resources and addresses; and in path names – such as PID file name – in the file system). More...
 
fs::path m_exec_path
 Absolute, lexically normalized canonical path to the executable entity (which is not a directory), as it would appear in a command line or exec()-like invocation when actually invoking the application. More...
 
util::user_id_t m_user_id
 The application must run as this user ID (UID). Files and other shared resources shall have this owner. More...
 
util::group_id_t m_group_id
 The application must run as this group ID (GID). Files and other shared resources shall have this owner. More...
 

Related Functions

(Note that these are not member functions.)

std::ostream & operator<< (std::ostream &os, const App &val)
 Prints string representation of the given App to the given ostream. More...
 

Detailed Description

A description of an application in this ipc::session inter-process communication universe.

An application is, at least roughly speaking, 1-1 with a distinct executable presumably interested in communicating with another such executable. A process is an instance of an application that has begun execution at some point.

An App is a description of an application, and typically used (at least after program initialization, before actual IPC begins) only as supertype of Client_app and/or Server_app. It is possible that 2+ Apps exist but describe one actual application, in different roles. 2+ such Apps must have all members equal to each other respectively. In particular see App::m_name.

This is a data store (and a simple one). The same holds of Client_app and Server_app. As of this writing there are no rigid rules as to the existence of an App/Client_app/Server_app with this or that stored inside. Make them all day long, if you want! More restrictions shall come into play only when passing various App objects and sub-objects (in some form) to ipc::session APIs, most notably the Session concept and buddies.

However, to be useful, we suggest the following convention. Some key ipc::session APIs may rely on it.

App, Client_app, Server_app registry conventions

Warning
Right off the bat, hopefully where it's visible, we alert you to a gotcha. It is implied below, but to put a fine point on it: Once you've set up your App, Client_app, Server_app objects, they need to stay alive at least past any session::Client_session and session::Session_server objects into which you pass their reference(s). They will not be copied, and if they're destroyed early, you may be hit by nasty accessing-invalid-memory undefined behaviors including but not limited to crashing.

Back to the conventions:

Thus one would end up with, after initialization of each process wishing to participate in a given IPC universe:

There should be no need, from this moment on, to copy any App, Client_app, or Server_app. It shall be passed by const reference.

Definition at line 87 of file app.hpp.

Member Typedef Documentation

◆ Master_set

using ipc::session::App::Master_set = boost::unordered_map<std::string, App>

Type for storing master repository of all Apps.

See App doc header for discussion.

Rationale: Chosen type (also applies to Client_app::Master_set and Server_app::Master_set)

It is unordered_, simply because there was not any particularly compelling reason to impose an order. (Admittedly: alphabetical order by m_name might have been nice in some contexts, like if someone wanted to pretty-print a Master_set. Ah, well. It is set now. Prints can be tweaked to sort anyway; as of this writing Flow-IPC does not print a Master_set anywhere.)

Using unordered_map (instead of unordered_flat_map) is pretty good here, as this way there is pointer stability. On one hand the implied – not as of this writing formally required – preferred pattern of use is for the user to set up their IPC universe, including these Master_sets, before any IPC happens – and then never change any of the data therein. On the other hand, "implied preferred pattern" be damned, it is conceivable a user would at some point, after giving some API a Master_set, add an App to that set. In that case pointer stability is an asset; any memorized App addresses won't become invalid on rehash.

Performance is not a concern here: lookups are rare; sizes are small. Hence no need to mess with _node_map and so forth.

Definition at line 112 of file app.hpp.

Friends And Related Function Documentation

◆ operator<<()

std::ostream & operator<< ( std::ostream &  os,
const App &  val 
)
related

Prints string representation of the given App to the given ostream.

Parameters
osStream to which to write.
valObject to serialize.
Returns
os.

Definition at line 130 of file app.cpp.

References m_exec_path, m_group_id, m_name, and m_user_id.

Member Data Documentation

◆ m_exec_path

fs::path ipc::session::App::m_exec_path

Absolute, lexically normalized canonical path to the executable entity (which is not a directory), as it would appear in a command line or exec()-like invocation when actually invoking the application.

Formally (refer to cppreference.com filesystem::path doc page):

  • There is no root-name: No Windows drive letters ("C:"), no network file share ("//share_name"), etc.
  • It is a Unix path: Only forward-slash is used as separator, and that character always is a separator.
  • It is absolute: It starts with forward-slash.
  • It is lexically normalized: See reference, but essentially it means no more than one slash in a row, no dot components, no dot-dot components. (Note: dots and dot-dots can appear – but an entire component cannot comprise solely such a sequence; where component means: a thing preceded by slash and succeeded by slash or end-of-path.)

Do note that because of the "as it would appear in a command line..." requirement this indirectly restricts how processes are to be invoked in this system: always via 1, absolute, lexically normal path to the executable. (Do also note this still does not necessarily force an unambiguous way to invoke an application installed at a given location: sym-links, at least, introduce an infinite number of ways to refer to the same binary. That said, at least lexical normalization can be done programmatically in fs, and sym-link following path resolution is also separately supplied by fs.)

Definition at line 200 of file app.hpp.

Referenced by operator<<(), and ipc::session::Session_server_impl< Session_server_t, Server_session_t >::Session_server_impl().

◆ m_group_id

util::group_id_t ipc::session::App::m_group_id

The application must run as this group ID (GID). Files and other shared resources shall have this owner.

Definition at line 206 of file app.hpp.

Referenced by ipc::session::ensure_resource_owner_is_app(), operator<<(), and ipc::session::Session_server_impl< Session_server_t, Server_session_t >::Session_server_impl().

◆ m_name

std::string ipc::session::App::m_name

Brief application name, readable to humans and unique across all other applications' names; used both as a short programmatic key in shared resource naming (including as a folder in Shared_name for kernel-persistent resources and addresses; and in path names – such as PID file name – in the file system).

Convention: mandated use as key

Neither App nor any nearby sub-class or alias of App (Client_app, Server_app) shall be used as the key type in an associative container (e.g., set, unordered_map). Instead App::m_name shall be used as the key when lookup by distinct application is desired. Two scenarios come to mind:

  • You want to store a set of applications fitting some criterion/a, but this is not some master repository of App objects in the first place – rather it is referring to some subset of such a master repository.
    • Then, store simply a set or unordered_set (etc.) of std::string m_names.
      • Rationale: The basic desired operation here is an existence-check (is application X present, based on some definition of present?). m_name is by definition guaranteed to be distinct from all others. Hence storing such strings alone is sufficient and reasonably efficient while also not relying on App address uniqueness for lookup (which, while efficient, is a pain to maintain).
  • You want to store some master repository of App objects, with all their config such as UID, GID, etc.
    • Then, store a map or unordered_map, with the keys being std::string m_names, while the values are filled-out App objects (or objects of App sub-class) – with the guarantee that M[name].m_name == name for all names in any such M.
      • Rationale: Same as above; but in addition to being able to perform existence-check by m_name, one can also iterate through the master details of all the applications and/or lookup a given application's master details.

Due to these conventions:

  • We do not supply the usual complement of associative-container "stuff" for App and buddies: equality, less-than, hashing. We do not want to encourage direct App storage that way.
  • The idea is: When such storage is desired, use that usual complement of associative-container "stuff" that is already supplied for std::string, as applied to App::m_name.

Digression regarding rationale: Why use m_name, and not (say) const App*, as the key in associative lookups? Answer: It was considered. Due to the infrequency of such lookups, combined with the debug-friendliness/expressiveness of referring to a distinct app by its user-readable name, the lookup-by-name convention felt more straightforward and convenient. Plus, the address of an object stored in a container may change while it is being built, which would add an element of brittleness. One could also use an iterator as a key, but then the registry container would be mandated to be iterator-stable-under-insertion, and that brings an annoying host of worries. Indexing by string name is solid by comparison, if a bit slower.

Conventions: Naming

Must begin with an ASCII alphabetical character and otherwise consist of only ASCII alphanumerics (so, notably, no underscores: use camelCase to separate words, per the convention for Shared_name components; see its doc header). While that is partially style-driven, the following is an important guarantee for related Shared_name and fs::path semantics:

  • Must not contain a util::Shared_name::S_SEPARATOR (which, notably, is the underscore).
  • Must not contain a forward-slash or any other file system path separator.
  • Must not contain a dot or any other conceivable extension separator.

Therefore:

  • In Shared_name paths one can embed m_name by preceding and/or succeeding it with a util::Shared_name::S_SEPARATOR, thus making it a full or partial folder name.
  • In file system paths one can embed m_name by preceding and/or succeeding it with a forward-slash, thus making it a full or partial directory name.
  • In either: one can embed m_name by preceding and/or succeeding it with a dot as an extension separator.
Note
Enforced, in part: Session_server ctor (all variants) emits error::Code::S_INVALID_ARGUMENT, if the Server_app's – or any registered Client_app's – m_name is empty or contains util::Shared_name::S_SEPARATOR.

So if m_name is "abcDef" one can do things like /some/dir/abcDef/some_file and /some/dir/abcDef.pid/file and /some/dir/prefix.abcDef.3 (file-system example) or "_some_dir_abcDef_moreStuff" (Shared_name example). I.e., m_name can be safely used as a conceptual "token," even when combined with path/name separators and dot-extension naming.

Definition at line 179 of file app.hpp.

Referenced by ipc::session::shm::classic::Session_server< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::app_shm_ptr(), ipc::session::shm::arena_lend::jemalloc::Session_server< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::app_shm_ptr(), ipc::session::shm::classic::Session_server< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::init_app_shm_as_needed(), ipc::session::shm::arena_lend::jemalloc::Session_server< MQ_TYPE_OR_NONE, TRANSMIT_NATIVE_HANDLES, Mdt_payload >::init_app_shm_as_needed(), ipc::transport::struc::shm::rpc::Client_context< Client_session_t >::on_session_hosed(), operator<<(), and ipc::session::Session_server_impl< Session_server_t, Server_session_t >::Session_server_impl().

◆ m_user_id

util::user_id_t ipc::session::App::m_user_id

The application must run as this user ID (UID). Files and other shared resources shall have this owner.

Definition at line 203 of file app.hpp.

Referenced by ipc::session::ensure_resource_owner_is_app(), operator<<(), and ipc::session::Session_server_impl< Session_server_t, Server_session_t >::Session_server_impl().


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