Flow-IPC 1.0.2
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
61static_assert(false, "IPC_KERNEL_PERSISTENT_RUN_DIR (/var/run) semantics require Unix; "
62 "tested in Linux specifically only.");
63#endif
64/**
65 * Absolute path to the directory (without trailing separator) in the file system where kernel-persistent
66 * runtime, but not temporary, information shall be placed. Kernel-persistent means that it'll disappear
67 * at reboot; runtime, but not temporary, means it's... not the designated temporary-data directory (informally:
68 * not /tmp). Informally: just know that it is /var/run, and that it stores things such as process-ID (PID)
69 * files.
70 *
71 * It is a Unix path, absolute (starts with forward-slash), and lexically normal (and lacks a root-name).
72 */
73extern const fs::path IPC_KERNEL_PERSISTENT_RUN_DIR;
74
75// Free functions.
76
77/**
78 * Internal (to ::ipc) utility that invokes the given function that invokes a boost.interprocess operation
79 * that is documented to throw `bipc::interprocess_exception` on failure; if indeed it throws the utility
80 * emits an error in the Flow error-reporting style. On error it logs WARNING with all available details.
81 *
82 * ### Background ###
83 * boost.interprocess has a number of operations that are documented to throw the aforementioned exception
84 * on error -- without any alternate way of reporting an error such as through an out-arg. Moreover the
85 * exception itself is not any standard runtime-exception type but rather a custom thing. This is somewhat
86 * annoying; and various parts of ::ipc want to emit errors in a consistent way. That does *not* mean
87 * we must only emit some `transport::error::Code::*` or whatever, but we should emit a native-based #Error_code
88 * if applicable, either as an out-arg or as a `flow::error::Runtime_error` wrapping it, or indeed one of our
89 * own codes otherwise (or if it is more applicable).
90 *
91 * So this helper standardizes that stuff.
92 *
93 * @tparam Func
94 * Functor that takes no args and returns nothing.
95 * @param logger_ptr
96 * Logger to use for logging subsequently.
97 * @param err_code
98 * `err_code` as-if passed to our API. `*err_code` shall be set if not null depending on success/failure;
99 * if null and no problem, won't throw; if null and problem will throw `Runtime_error` containing a truthy
100 * #Error_code. That's the usual Flow-style error emission semantics.
101 * @param misc_bipc_lib_error
102 * If `func` throws, and we are unable to suss out the system error that caused it, then emit
103 * this value. E.g.: transport::Code::S_MQ_BIPC_MISC_LIBRARY_ERROR makes sense if creating
104 * a `bipc::message_queue`; or a similar one for SHM-related parts of `bipc`; etc.
105 * @param context
106 * Description for logging of the op being attempted, in case there is an error. Compile-time-known strings
107 * are best, as this is not protected by a filtering macro and hence will be evaluated no matter what.
108 * @param func
109 * `func()` shall be executed synchronously.
110 */
111template<typename Func>
112void op_with_possible_bipc_exception(flow::log::Logger* logger_ptr, Error_code* err_code,
113 const Error_code& misc_bipc_lib_error,
114 String_view context,
115 const Func& func);
116
117/**
118 * Writes a byte to the given pipe writer. If any error occurs => undefined behavior (assert may trip).
119 * If it would-block... it will block. So: only use if your algorithm has made sure you will never reach the
120 * pipe's capacity.
121 *
122 * @param logger_ptr
123 * Logger to use for logging subsequently.
124 * @param pipe
125 * The pipe.
126 */
127void pipe_produce(flow::log::Logger* logger_ptr, Pipe_writer* pipe);
128
129/**
130 * Reads a byte via the given pipe reader. If any error occurs => undefined behavior (assert may trip).
131 * If it would-block... it will block. So: only use if your algorithm has made sure you have a byte in there.
132 *
133 * @param logger_ptr
134 * Logger to use for logging subsequently.
135 * @param pipe
136 * The pipe.
137 */
138void pipe_consume(flow::log::Logger* logger_ptr, Pipe_reader* pipe);
139
140/**
141 * Builds an absolute name according to the path convention explained in Shared_name class doc header;
142 * this overload applies to resources *outside* the ipc::session paradigm. Typically one
143 * would then add a Shared_name::S_SEPARATOR and then purpose-specific path component(s) (via `/=` or similar).
144 *
145 * Behavior is undefined if a path fragment argument is empty (assertion may trip).
146 *
147 * @param resource_type
148 * Resource type constant. Typically it is available as a `S_RESOURCE_TYPE_ID` constant in some class;
149 * otherwise as a `Shared_name::S_RESOURCE_TYPE_ID_*` constant.
150 * @return Absolute path not ending in `S_SEPARATOR`, typically to be appended with a `S_SEPARATOR` and more
151 * component(s) by the caller.
152 */
154
155/**
156 * Implementation of `Persistent_object::for_each_persistent()`; for example see
157 * shm::classic::Pool_arena::for_each_persistent(). It relies on the OS feature wherein each particular
158 * `Persistent_object` (kernel-persistent object) type is listed in flat fashion in a particular
159 * directory; `persistent_obj_dev_dir_path` must specify this directory.
160 *
161 * Conceptually, we shall perform `ls D/`, where `D` is `persistent_obj_dev_dir_path`. Then for each
162 * resulting `D/N`, we shall call `handle_name_func(N)`.
163 *
164 * ### Errors (or lack thereof) ###
165 * There is no error condition. If `persistent_obj_dev_dir_path` does not exist, or we lack permissions to
166 * look therein, it merely means it cannot contain any relevant items; hence `handle_name_func()` is not invoked.
167 *
168 * @tparam Handle_name_func
169 * See, e.g., shm::classic::Pool_arena::for_each_persistent().
170 * @param persistent_obj_dev_dir_path
171 * This must be an absolute path, or behavior is undefined (assertion may trip). See above.
172 * @param handle_name_func
173 * See `Handle_name_func`.
174 */
175template<typename Handle_name_func>
176void for_each_persistent_impl(const fs::path& persistent_obj_dev_dir_path, const Handle_name_func& handle_name_func);
177
178/**
179 * Equivalent to shm::classic::Pool_arena::for_each_persistent(). Provided here (for internal purposes as of this
180 * writing) to avoid a little circular-inter-component-dependent problem: Posix_mq_handle::for_each_persistent()
181 * needs us; but accessing `Pool_arena` would mean `ipc_core` Flow-IPC sub-component needing `ipc_shm`
182 * sub-component as a dependency... but the reverse is already naturally the case. See ::ipc namespace doc header
183 * for discussion of the component hierarchy and how we prefer to avoid circular dependencies therein.
184 *
185 * @tparam Handle_name_func
186 * See above.
187 * @param handle_name_func
188 * See above.
189 */
190template<typename Handle_name_func>
191void for_each_persistent_shm_pool(const Handle_name_func& handle_name_func);
192
193/**
194 * Equivalent to shm::classic::Pool_arena::remove_persistent(). Provided for similar reason to that described
195 * in for_each_persistent_shm_pool() doc header nearby.
196 *
197 * @param logger_ptr
198 * See above.
199 * @param name
200 * See above.
201 * @param err_code
202 * See above.
203 */
204void remove_persistent_shm_pool(flow::log::Logger* logger_ptr, const Shared_name& name, Error_code* err_code);
205
206} // namespace ipc::util
207
209{
210
211// Types.
212
213// Find doc headers near the bodies of these compound types.
214
216
217// Free functions.
218
219/**
220 * Prints string representation of the given `Timer_event_emitter` to the given `ostream`.
221 *
222 * @relatesalso Timer_event_emitter
223 *
224 * @param os
225 * Stream to which to write.
226 * @param val
227 * Object to serialize.
228 * @return `os`.
229 */
230std::ostream& operator<<(std::ostream& os, const Timer_event_emitter& val);
231
232} // 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:209
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:161
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:131
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:115
flow::Error_code Error_code
Short-hand for flow::Error_code which is very common.
Definition: common.hpp:298