Flow-IPC 1.0.0
Flow-IPC project: Full implementation reference.
util_fwd.hpp
Go to the documentation of this file.
1/* Flow-IPC: Core
2 * Copyright 2023 Akamai Technologies, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the
5 * "License"); you may not use this file except in
6 * compliance with the License. You may obtain a copy
7 * of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in
12 * writing, software distributed under the License is
13 * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
14 * CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing
16 * permissions and limitations under the License. */
17
18/// @file
19#pragma once
20
21#include "ipc/util/util_fwd.hpp"
23#include <flow/common.hpp>
24#include <boost/array.hpp>
25
26namespace ipc::util
27{
28
29// Types.
30
31/// Short-hand for anonymous pipe write end.
32using Pipe_writer = boost::asio::writable_pipe;
33
34/// Short-hand for anonymous pipe read end.
35using Pipe_reader = boost::asio::readable_pipe;
36
37// Constants.
38
39/**
40 * Maps general Permissions_level specifier to low-level #Permissions value, when the underlying resource
41 * is in the file-system and is either accessible (read-write in terms of file system) or inaccessible.
42 * Examples of such resources are SHM pools (in Linux living in "/dev/shm") and POSIX MQs ("/dev/mqueue").
43 *
44 * See any additional user-facing notes in shared_resource_permissions() doc header.
45 */
46extern const boost::array<Permissions, size_t(Permissions_level::S_END_SENTINEL)>
48
49/**
50 * Maps general Permissions_level specifier to low-level #Permissions value, when the underlying resource
51 * is in the file-system (e.g., a file) and is *produced* (and therefore always writable) by the owning (creating,
52 * updating) user; but *consumed* (and therefore at most readable, never writable) by potentially other processes,
53 * and therefore possibly other users (e.g., group access or unrestricted access -- but only for reading either way).
54 * For example a PID file is typically only writable by the daemon's user but may be readable or inaccessible by
55 * other users.
56 */
57extern const boost::array<Permissions, size_t(Permissions_level::S_END_SENTINEL)>
59
60#ifndef FLOW_OS_LINUX
61# error "IPC_KERNEL_PERSISTENT_RUN_DIR (/var/run) semantics require Unix; tested in Linux specifically only."
62#endif
63/**
64 * Absolute path to the directory (without trailing separator) in the file system where kernel-persistent
65 * runtime, but not temporary, information shall be placed. Kernel-persistent means that it'll disappear
66 * at reboot; runtime, but not temporary, means it's... not the designated temporary-data directory (informally:
67 * not /tmp). Informally: just know that it is /var/run, and that it stores things such as process-ID (PID)
68 * files.
69 *
70 * It is a Unix path, absolute (starts with forward-slash), and lexically normal (and lacks a root-name).
71 */
72extern const fs::path IPC_KERNEL_PERSISTENT_RUN_DIR;
73
74// Free functions.
75
76/**
77 * Internal (to ::ipc) utility that invokes the given function that invokes a boost.interprocess operation
78 * that is documented to throw `bipc::interprocess_exception` on failure; if indeed it throws the utility
79 * emits an error in the Flow error-reporting style. On error it logs WARNING with all available details.
80 *
81 * ### Background ###
82 * boost.interprocess has a number of operations that are documented to throw the aforementioned exception
83 * on error -- without any alternate way of reporting an error such as through an out-arg. Moreover the
84 * exception itself is not any standard runtime-exception type but rather a custom thing. This is somewhat
85 * annoying; and various parts of ::ipc want to emit errors in a consistent way. That does *not* mean
86 * we must only emit some `transport::error::Code::*` or whatever, but we should emit a native-based #Error_code
87 * if applicable, either as an out-arg or as a `flow::error::Runtime_error` wrapping it, or indeed one of our
88 * own codes otherwise (or if it is more applicable).
89 *
90 * So this helper standardizes that stuff.
91 *
92 * @tparam Func
93 * Functor that takes no args and returns nothing.
94 * @param logger_ptr
95 * Logger to use for logging subsequently.
96 * @param err_code
97 * `err_code` as-if passed to our API. `*err_code` shall be set if not null depending on success/failure;
98 * if null and no problem, won't throw; if null and problem will throw `Runtime_error` containing a truthy
99 * #Error_code. That's the usual Flow-style error emission semantics.
100 * @param misc_bipc_lib_error
101 * If `func` throws, and we are unable to suss out the system error that caused it, then emit
102 * this value. E.g.: transport::Code::S_MQ_BIPC_MISC_LIBRARY_ERROR makes sense if creating
103 * a `bipc::message_queue`; or a similar one for SHM-related parts of `bipc`; etc.
104 * @param context
105 * Description for logging of the op being attempted, in case there is an error. Compile-time-known strings
106 * are best, as this is not protected by a filtering macro and hence will be evaluated no matter what.
107 * @param func
108 * `func()` shall be executed synchronously.
109 */
110template<typename Func>
111void op_with_possible_bipc_exception(flow::log::Logger* logger_ptr, Error_code* err_code,
112 const Error_code& misc_bipc_lib_error,
113 String_view context,
114 const Func& func);
115
116/**
117 * Writes a byte to the given pipe writer. If any error occurs => undefined behavior (assert may trip).
118 * If it would-block... it will block. So: only use if your algorithm has made sure you will never reach the
119 * pipe's capacity.
120 *
121 * @param logger_ptr
122 * Logger to use for logging subsequently.
123 * @param pipe
124 * The pipe.
125 */
126void pipe_produce(flow::log::Logger* logger_ptr, Pipe_writer* pipe);
127
128/**
129 * Reads a byte via the given pipe reader. If any error occurs => undefined behavior (assert may trip).
130 * If it would-block... it will block. So: only use if your algorithm has made sure you have a byte in there.
131 *
132 * @param logger_ptr
133 * Logger to use for logging subsequently.
134 * @param pipe
135 * The pipe.
136 */
137void pipe_consume(flow::log::Logger* logger_ptr, Pipe_reader* pipe);
138
139/**
140 * Builds an absolute name according to the path convention explained in Shared_name class doc header;
141 * this overload applies to resources *outside* the ipc::session paradigm. Typically one
142 * would then add a Shared_name::S_SEPARATOR and then purpose-specific path component(s) (via `/=` or similar).
143 *
144 * Behavior is undefined if a path fragment argument is empty (assertion may trip).
145 *
146 * @param resource_type
147 * Resource type constant. Typically it is available as a `S_RESOURCE_TYPE_ID` constant in some class;
148 * otherwise as a `Shared_name::S_RESOURCE_TYPE_ID_*` constant.
149 * @return Absolute path not ending in `S_SEPARATOR`, typically to be appended with a `S_SEPARATOR` and more
150 * component(s) by the caller.
151 */
153
154/**
155 * Implementation of `Persistent_object::for_each_persistent()`; for example see
156 * shm::classic::Pool_arena::for_each_persistent(). It relies on the OS feature wherein each particular
157 * `Persistent_object` (kernel-persistent object) type is listed in flat fashion in a particular
158 * directory; `persistent_obj_dev_dir_path` must specify this directory.
159 *
160 * Conceptually, we shall perform `ls D/`, where `D` is `persistent_obj_dev_dir_path`. Then for each
161 * resulting `D/N`, we shall call `handle_name_func(N)`.
162 *
163 * ### Errors (or lack thereof) ###
164 * There is no error condition. If `persistent_obj_dev_dir_path` does not exist, or we lack permissions to
165 * look therein, it merely means it cannot contain any relevant items; hence `handle_name_func()` is not invoked.
166 *
167 * @tparam Handle_name_func
168 * See, e.g., shm::classic::Pool_arena::for_each_persistent().
169 * @param persistent_obj_dev_dir_path
170 * This must be an absolute path, or behavior is undefined (assertion may trip). See above.
171 * @param handle_name_func
172 * See `Handle_name_func`.
173 */
174template<typename Handle_name_func>
175void for_each_persistent_impl(const fs::path& persistent_obj_dev_dir_path, const Handle_name_func& handle_name_func);
176
177/**
178 * Equivalent to shm::classic::Pool_arena::for_each_persistent(). Provided here (for internal purposes as of this
179 * writing) to avoid a little circular-inter-component-dependent problem: Posix_mq_handle::for_each_persistent()
180 * needs us; but accessing `Pool_arena` would mean `ipc_core` Flow-IPC sub-component needing `ipc_shm`
181 * sub-component as a dependency... but the reverse is already naturally the case. See ::ipc namespace doc header
182 * for discussion of the component hierarchy and how we prefer to avoid circular dependencies therein.
183 *
184 * @tparam Handle_name_func
185 * See above.
186 * @param handle_name_func
187 * See above.
188 */
189template<typename Handle_name_func>
190void for_each_persistent_shm_pool(const Handle_name_func& handle_name_func);
191
192/**
193 * Equivalent to shm::classic::Pool_arena::remove_persistent(). Provided for similar reason to that described
194 * in for_each_persistent_shm_pool() doc header nearby.
195 *
196 * @param logger_ptr
197 * See above.
198 * @param name
199 * See above.
200 * @param err_code
201 * See above.
202 */
203void remove_persistent_shm_pool(flow::log::Logger* logger_ptr, const Shared_name& name, Error_code* err_code);
204
205} // namespace ipc::util
206
208{
209
210// Types.
211
212// Find doc headers near the bodies of these compound types.
213
215
216// Free functions.
217
218/**
219 * Prints string representation of the given `Timer_event_emitter` to the given `ostream`.
220 *
221 * @relatesalso Timer_event_emitter
222 *
223 * @param os
224 * Stream to which to write.
225 * @param val
226 * Object to serialize.
227 * @return `os`.
228 */
229std::ostream& operator<<(std::ostream& os, const Timer_event_emitter& val);
230
231} // namespace ipc::util::sync_io
String-wrapping abstraction representing a name uniquely distinguishing a kernel-persistent entity fr...
An object of this type, used internally to implement sync_io-pattern objects that require timer event...
Contains common code, as well as important explanatory documentation in the following text,...
Definition: util_fwd.hpp:208
std::ostream & operator<<(std::ostream &os, const Timer_event_emitter &val)
Prints string representation of the given Timer_event_emitter to the given ostream.
Flow-IPC module containing miscellaneous general-use facilities that ubiquitously used by ~all Flow-I...
bipc::permissions Permissions
Short-hand for Unix (POSIX) permissions class.
Definition: util_fwd.hpp:155
void remove_persistent_shm_pool(flow::log::Logger *logger_ptr, const Shared_name &pool_name, Error_code *err_code)
Equivalent to shm::classic::Pool_arena::remove_persistent().
Definition: util.cpp:119
@ S_END_SENTINEL
Sentinel: not a valid value. May be used to, e.g., size an array<> mapping from Permissions_level.
void for_each_persistent_impl(const fs::path &persistent_obj_dev_dir_path, const Handle_name_func &handle_name_func)
Implementation of Persistent_object::for_each_persistent(); for example see shm::classic::Pool_arena:...
Definition: util.hpp:90
void pipe_produce(flow::log::Logger *logger_ptr, Pipe_writer *pipe)
Writes a byte to the given pipe writer.
Definition: util.cpp:67
const boost::array< Permissions, size_t(Permissions_level::S_END_SENTINEL)> SHARED_RESOURCE_PERMISSIONS_LVL_MAP
Maps general Permissions_level specifier to low-level Permissions value, when the underlying resource...
Definition: util.cpp:34
Shared_name build_conventional_non_session_based_shared_name(const Shared_name &resource_type)
Builds an absolute name according to the path convention explained in Shared_name class doc header; t...
void for_each_persistent_shm_pool(const Handle_name_func &handle_name_func)
Equivalent to shm::classic::Pool_arena::for_each_persistent().
Definition: util.hpp:130
void pipe_consume(flow::log::Logger *logger_ptr, Pipe_reader *pipe)
Reads a byte via the given pipe reader.
Definition: util.cpp:96
boost::asio::writable_pipe Pipe_writer
Short-hand for anonymous pipe write end.
Definition: util_fwd.hpp:32
const boost::array< Permissions, size_t(Permissions_level::S_END_SENTINEL)> PRODUCER_CONSUMER_RESOURCE_PERMISSIONS_LVL_MAP
Maps general Permissions_level specifier to low-level Permissions value, when the underlying resource...
Definition: util.cpp:42
const fs::path IPC_KERNEL_PERSISTENT_RUN_DIR
Absolute path to the directory (without trailing separator) in the file system where kernel-persisten...
Definition: util.cpp:63
boost::asio::readable_pipe Pipe_reader
Short-hand for anonymous pipe read end.
Definition: util_fwd.hpp:35
void op_with_possible_bipc_exception(flow::log::Logger *logger_ptr, Error_code *err_code, const Error_code &misc_bipc_lib_error, String_view context, const Func &func)
Internal (to ipc) utility that invokes the given function that invokes a boost.interprocess operation...
Definition: util.hpp:34
flow::util::String_view String_view
Short-hand for Flow's String_view.
Definition: util_fwd.hpp:109
flow::Error_code Error_code
Short-hand for flow::Error_code which is very common.
Definition: common.hpp:297