36#include <flow/util/stat/stat_set.hpp>
37#include <flow/util/util.hpp>
38#include <boost/range/adaptor/transformed.hpp>
49 flow::async::Task_asio_err&& shm_channel_error_handler)
51 return std::shared_ptr<Shm_session>(
new Shm_session{logger, std::move(shm_channel), session_token_non_nil,
52 std::move(shm_channel_error_handler)});
57 flow::async::Task_asio_err&& shm_channel_error_handler) :
60 m_remote_process_id(shm_channel.remote_peer_process_credentials().process_id()),
64 m_shm_channel(std::in_place,
65 get_logger(), std::move(shm_channel), transport::struc::Channel_base::S_SERIALIZE_VIA_HEAP,
66 session_token_non_nil),
67 m_shm_channel_error_handler(std::move(shm_channel_error_handler)),
68 m_serial_task_loop(logger,
"JSSS_" + std::to_string(m_remote_process_id))
70 using flow::async::reset_this_thread_pinning;
72 FLOW_LOG_TRACE(
"Constructing [" <<
this <<
"].");
84 m_shm_channel->expect_msgs(schema::IpcShmMessage::Which::LEND_ARENA,
85 [
this](
auto&& req)
mutable
90 const auto& reader = req->body_root().getLendArena();
95 &&
m_shm_channel->expect_msgs(schema::IpcShmMessage::Which::LEND_POOL,
96 [
this](
auto&& req)
mutable
101 const auto& reader = req->body_root().getLendPool();
102 receive_shm_pool(reader.getCollectionId(), reader.getPoolId(), reader.getPoolSize());
106 assert(ok &&
"struc::Channel::expect_msgs() is not supposed to report hose channel before start().");
159 FLOW_LOG_INFO(
"Shm_session [" <<
this <<
"] shutdown: "
160 "~Final state (includes ~final this-session + ~current global):"
161 "\n" << (
info_dump(&dump), dump) <<
'.');
178 auto& cur_arena = cur_map_pair.first;
179 auto& cur_listener_ptr = cur_map_pair.second;
180 cur_arena->remove_shm_pool_listener(cur_listener_ptr.get());
250 auto& borrower_repository = Borrower_shm_pool_collection_repository<Arena>::get_instance();
251 for (
const auto& cur_map_pair : borrower_pool_id_map)
253 auto cur_collection_id = cur_map_pair.first;
254 const auto& cur_shm_pool_ids = cur_map_pair.second;
256 for (
const auto cur_shm_pool_id : cur_shm_pool_ids)
258 borrower_repository.deregister_shm_pool(
m_remote_process_id, cur_collection_id, cur_shm_pool_id);
282 auto do_it_func = [
this, err_code]()
286 bool expected_pre =
true;
287 m_connected.compare_exchange_strong(expected_pre,
false);
289 &&
"By our contract we are to be called at most once, on m_shm_channel hosing being self-reported; "
290 "yet disconnected-flag was already true. Bug in struc::Channel or in Shm_session.");
292 FLOW_LOG_WARNING(
"Relaying channel-hosing (reason [" << err_code <<
"] [" << err_code.message() <<
"]).");
313 using flow::util::key_exists;
319 FLOW_LOG_WARNING(
"Disconnected, so ignoring arena lending attempt.");
328 FLOW_LOG_WARNING(
"Arena [" << collection_id <<
"] was already lent through this session; ignoring repeated "
329 "arena lending attempt (user error?).");
334 const auto result_pair
336 assert(result_pair.second &&
"We just checked for duplicate.");
340 auto lend_arena = message.body_root()->initLendArena();
342 lend_arena.setPoolNameBase(Owner_spc_impl<Arena>{*arena}.get_pool_name_base().str());
350 assert(ok &&
"We just inserted this; erase must succeed.");
359 arena->add_shm_pool_listener(result_pair.first->second.get());
360 assert(ok &&
"We just created a fresh listener; add must succeed.");
369 FLOW_LOG_INFO(
"Successfully registered arena [" << collection_id <<
"] (opposing owner ID (PID) "
376 for (
const auto& cur_shm_pool : shm_pools)
391 FLOW_LOG_WARNING(
"Disconnected, so ignoring pool lending attempt.");
398 auto lend_pool = message.body_root()->initLendPool();
399 lend_pool.setCollectionId(collection_id);
400 lend_pool.setPoolId(shm_pool->get_id());
401 lend_pool.setPoolSize(shm_pool->get_size());
473 FLOW_LOG_TRACE(
"Pool removal notification for pool [" << shm_pool->get_id() <<
"], collection [" <<
474 collection_id <<
"]; RemovePool not re-implemented (possible @todo), borrower cleanup deferred to "
475 "session teardown.");
490 const auto response =
m_shm_channel->sync_request(&message,
nullptr, &err_code);
496 FLOW_LOG_WARNING(
"Failed to complete request on channel, operation [" << operation <<
"] due to "
497 "error [" << err_code <<
"] [" << err_code.message() <<
"]. Reporting channel-hosing.");
502 FLOW_LOG_WARNING(
"Failed to send request on already hosed channel, operation [" << operation <<
"]. "
503 "The official channel-hosing would have been reported/is being reported concurrently "
504 "via on-channel-hosed handler.");
512 assert(response->body_root().getResponse().getSuccess()
513 &&
"Borrower indicated failure; should have aborted there instead.");
515 FLOW_LOG_TRACE(
"Successfully fulfilled [" << operation <<
"] sync request.");
523 assert(original_message);
526 auto response = message.body_root()->initResponse();
527 response.setSuccess(
true);
530 if (!
m_shm_channel->send(&message, original_message, &err_code))
532 FLOW_LOG_WARNING(
"Failed to send reponse message on already hosed channel, operation [" << operation <<
"]. "
533 "The official channel-hosing would have been reported/is being reported concurrently "
534 "via on-channel-hosed handler.");
538 FLOW_LOG_WARNING(
"Failed to send message on channel, operation [" << operation <<
"] due to "
539 "error [" << err_code <<
"] [" << err_code.message() <<
"]. Reporting channel-hosing.");
544 FLOW_LOG_TRACE(
"Successfully sent [" << operation <<
"] response message.");
551 using flow::util::stat::fetch_add;
552 using flow::util::stat::update_hi_wmark;
556 Borrower_shm_pool_collection_repository<Arena>::get_instance()
560 const auto insert_result =
563 assert(insert_result.second &&
"Duplicate collection; opposing process double-lent arena -- bug.");
577 using flow::util::stat::fetch_add;
578 using flow::util::stat::update_hi_wmark;
583 Borrower_shm_pool_collection_repository<Arena>::get_instance()
587 assert((iter !=
m_borrower_pool_id_map.end()) &&
"Pool opened fine, but collection not in local map; bug?");
589 const auto insert_result =
591 iter->second.insert(shm_pool_id);
592 assert(insert_result.second &&
"Pool opened fine, but pool ID already in local map; bug?");
613 m_collection_id(collection_id)
619 m_owner.lend_shm_pools(m_collection_id, shm_pools);
624 m_owner.lend_shm_pool(m_collection_id, shm_pool);
629 m_owner.remove_lender_shm_pool(m_collection_id, shm_pool);
634 using flow::util::stat::stats_assign;
635 using boost::adaptors::transformed;
644 constexpr size_t PITHY_N_ARENAS_MAX = 20;
646 assert(target_info_dump);
656 (&vec, verbose ? 0 : PITHY_N_ARENAS_MAX,
666 const auto vec_rng = vec | transformed([](
const auto& stats_ptr) ->
const Borrower_pool_stats&
667 {
return *stats_ptr; });
669 target_vec = vector<Borrower_pool_stats>{vec.size()};
670 auto target_vec_it = target_vec.begin();
671 for (
const auto& stats : vec_rng)
673 stats_assign(&(*target_vec_it++), stats);
699 return Pool_lookup_global_stats<Arena, false>::stats();
704 size_t per_arena_stats_sz_limit_or_0,
705 size_t* n_arenas_omitted)
708 .
stats(per_arena_stats, per_arena_stats_sz_limit_or_0, n_arenas_omitted);
716 Pool_lookup_global_stats<Arena, false>::stats_reset();
717 Borrower_shm_pool_collection_repository<Arena>::get_instance().stats_reset();
723 return os <<
'@' << &val;
static constexpr util::Fine_duration S_PING_PERIOD
The period with which each session-internal channel – notably the session master channel; also the in...
static constexpr util::Fine_duration S_IDLE_TIMEOUT
The idle timeout of each session-internal channel (see S_PING_PERIOD): if no low-level traffic – incl...
Singleton repository for borrowed SHM-pool data.
const Borrower_pool_stats & stats(Borrower_pool_stats_list *per_arena_stats, size_t per_arena_stats_sz_limit_or_0, size_t *n_arenas_omitted) const
Implements the borrower-side process-wide stats accessor; see jemalloc::Shm_session::borrower_pool_st...
void register_shm_pool(owner_id_t owner_id, collection_id_t collection_id, pool_id_t shm_pool_id, std::size_t shm_pool_size)
Registers a borrowed SHM-pool.
std::vector< Shm_pool_info > shm_pool_live_info() const
Implements the borrower-side process-wide live-pool-info accessor; see jemalloc::Shm_session::borrowe...
static Borrower_shm_pool_collection_repository & get_instance()
Returns the process-wide singleton instance of this class.
void register_collection(owner_id_t owner_id, collection_id_t collection_id, Shared_name &&pool_name_base)
Registers (or increments use of) a borrowed arena (collection) identified by arena ID (owner_id,...
Shm_pool_listener_impl(Shm_session &owner, collection_id_t collection_id)
Constructor.
void notify_created_shm_pool(const std::shared_ptr< Shm_pool > &shm_pool) override
Implements super-class API (see inner class doc header for recap).
void notify_initial_shm_pools(const std::set< std::shared_ptr< Shm_pool > > &shm_pools) override
Implements super-class API (notification called upon initial registration in lend_arena() in a synchr...
void notify_removed_shm_pool(const std::shared_ptr< Shm_pool > &shm_pool) override
Implements super-class API.
In SHM-jemalloc, a context between this process and a single (typically other) opposing process w/r/t...
const util::process_id_t m_remote_process_id
The other end's process ID, cached from m_shm_channel; used for registering borrowed items.
~Shm_session()
Constructors/destructor.
boost::unordered_map< std::shared_ptr< Arena >, std::unique_ptr< Shm_pool_listener_impl > > m_shm_pool_listener_map
Maps an arena to its SHM-pool listener; this is used for receiving changes in the SHM pools.
void info_dump(Info_dump *target_info_dump)
Fills-out the stats/info contents of the given stat::Shm_session_info_dump: a printable bundling of s...
static std::vector< Shm_pool_info > borrowed_shm_pool_live_info()
For informational/stats-adjacent purposes, returns information on currently open (and memory-mapped) ...
Shm_pool::size_t pool_offset_t
Short-hand for pool offset type.
Borrower_pool_stats m_borrower_pool_stats
Stats about borrower SHM-pool (and containing SHM-arena) borrowing (opening) and unborrowing (closing...
void lend_shm_pools(collection_id_t collection_id, const std::set< std::shared_ptr< Shm_pool > > &shm_pools)
Equivalent to lend_shm_pool(collection_id, P) for each P in shm_pools.
void send_response(const Shm_struc_channel::Msg_in *original_message, util::String_view operation)
Helper that sends ack to having received a thing that the opposing side sent via its send_sync_reques...
bool send_sync_request(Shm_struc_channel::Msg_out &message, util::String_view operation)
Helper that sends message over internal-use m_shm_channel and returns on ack (or failure to send).
Shm_pool::pool_id_t pool_id_t
Short-hand for pool ID type.
bool lend_arena(const std::shared_ptr< Arena > &arena)
Registers an arena for lending to the borrower process (usually a separate process) on the other end ...
void receive_arena(collection_id_t collection_id, Shared_name &&pool_name_base)
Borrows an arena shared by the lender: in thread W a/k/a m_serial_task_loop handle LendArena message.
static const Borrower_pool_lookup_global_stats & borrower_pool_lookup_global_stats()
Returns the process-wide borrower-side stat-set Borrower_pool_lookup_global_stats,...
void set_disconnected(const Error_code &err_code)
Helper that permanently sets m_connected true => false, so that lend_arena(), lend_object(),...
boost::unordered_map< collection_id_t, boost::unordered_set< pool_id_t > > m_borrower_pool_id_map
Per-collection set of borrowed pool IDs; used for cleanup in dtor.
void borrower_pool_stats_reset()
Resets borrower_pool_stats() – the per-*this-Shm_session view only; does not affect the process-wide ...
std::atomic< bool > m_connected
Whether the session is connected; true to start; when set to false m_shm_channel_error_handler is inv...
const Borrower_pool_stats & borrower_pool_stats() const
Returns the borrower-side stat-set Borrower_pool_stats limited to *this Shm_session – i....
bool lend_shm_pool(collection_id_t collection_id, const std::shared_ptr< Shm_pool > &shm_pool)
Registers a SHM pool for lending and sends messages to the borrower about it; returns on acknowledgme...
void remove_lender_shm_pool(collection_id_t collection_id, const std::shared_ptr< Shm_pool > &shm_pool)
As Shm_pool_listener_impl::notify_created_shm_pool() (by Ipc_arena) => lend_shm_pool(),...
static std::shared_ptr< Shm_session > create(flow::log::Logger *logger, Shm_channel &&shm_channel, const transport::struc::Session_token &session_token_non_nil, flow::async::Task_asio_err &&shm_channel_error_handler)
Creates an instance of this class; the resulting Shm_arena object is immediately ready to receive inc...
ipc::session::shm::arena_lend::Borrower_pool_stats_list Borrower_pool_stats_list
Alias for a (per-arena) stats-list type, as returned by borrower_pool_stats_process_wide().
std::ostream & operator<<(std::ostream &os, const Shm_session &val)
Prints string representation of the given Shm_session to the given ostream.
flow::async::Task_asio_err m_shm_channel_error_handler
Callback executed when a channel error code is emitted when using m_shm_channel.
static const Borrower_pool_stats & borrower_pool_stats_process_wide(Borrower_pool_stats_list *per_arena_stats=nullptr, size_t per_arena_stats_sz_limit_or_0=0, size_t *n_arenas_omitted=nullptr)
Returns the process-wide borrower-side stat-set Borrower_pool_stats – the running totals across all S...
void receive_shm_pool(collection_id_t collection_id, pool_id_t shm_pool_id, pool_offset_t pool_size)
Borrows a SHM pool from the lender: in thread W a/k/a m_serial_task_loop handle LendPool message.
ipc::shm::arena_lend::collection_id_t collection_id_t
Short-hand for pool-collection (a/k/a arena) ID type.
static void global_stats_reset()
Resets borrower_pool_lookup_global_stats() and borrower_pool_stats_process_wide().
std::optional< Shm_struc_channel > m_shm_channel
The channel used for transmitting SHM-pool messages.
flow::async::Single_thread_task_loop m_serial_task_loop
Task engine to process tasks in a serial manner (a/k/a thread W).
Shm_session(flow::log::Logger *logger, Shm_channel &&shm_channel, const transport::struc::Session_token &session_token_non_nil, flow::async::Task_asio_err &&shm_channel_error_handler)
Constructor (private due to shared_ptr factory pattern).
util::process_id_t get_remote_process_id() const
Returns the remote process ID.
Global stats singleton for either Owner_pool_lookup_global_stats or Borrower_pool_lookup_global_stats...
A Channel with a blobs pipe only (no handles pipe) that uses a Unix domain socket connection as the u...
typename Sync_io_obj::Msg_out Msg_out
Encapsulation of any out-message payload sent or meant to be sent via send() (et al) by a *this of th...
typename Sync_io_obj::Msg_in Msg_in
Encapsulation of any in-message instance received by a *this of this type.
String-wrapping abstraction representing a name uniquely distinguishing a kernel-persistent entity fr...
static Shared_name ct(const Source &src)
Copy-constructs from a char-sequence container such as string or util::String_view.
Support for SHM-backed ipc::session sessions and session-servers with the SHM-jemalloc (ipc::shm::are...
boost::uuids::uuid Session_token
A type used by struc::Channel for internal safety/security/auth needs.
::pid_t process_id_t
Syntactic-sugary type for POSIX process ID (integer).
flow::util::String_view String_view
Short-hand for Flow's String_view.
Log_component
The flow::log::Component payload enumeration containing various log components used by Flow-IPC inter...
flow::Error_code Error_code
Short-hand for flow::Error_code which is very common.
This is the friend facade of Owner_shm_pool_collection that exposes non-public APIs hidden from publi...
Printable (with knobs in contained util::stat::Info_dump_format) bundling of stats/info relevant to (...
size_t m_borrower_pool_stats_process_wide_per_arena_n_omitted
If m_fmt.m_verbose == false at Shm_session::info_dump() time, this is the # (possibly zero) of entrie...
arena_lend::stat::Borrower_pool_stats m_borrower_pool_stats_process_wide_total
Global stats from: static Shm_session::borrower_pool_stats_process_wide(): return value.
arena_lend::stat::Borrower_pool_stats m_borrower_pool_stats
Target Shm_session's stats from: Shm_session::borrower_pool_stats().
std::vector< arena_lend::stat::Borrower_pool_stats > m_borrower_pool_stats_process_wide_per_arena
Global stats from: static Shm_session::borrower_pool_stats_process_wide(): the per-arena out-arg.
util::stat::Info_dump_format m_fmt
Print-format knobs in effect at ostream << *this time.
std::vector< arena_lend::stat::Shm_pool_info > m_borrowed_shm_pool_live_info
Global info from: static Shm_session::shm_pool_live_info().
arena_lend::stat::Borrower_pool_lookup_global_stats m_borrower_pool_lookup_global_stats
Global stats from: static Shm_session::borrower_pool_lookup_global_stats().
Analogous subject matter to Owner_pool_lookup_global_stats but borrower-side.
Loosely similar subject matter to Owner_pool_stats but regarding the borrower-side view of SHM-pools,...
std::atomic< uint64_t > m_n_open_pools
(Gauge) Analogous to m_n_borrowed_arenas but counts individual in-arena SHM-pools.
std::atomic< uint64_t > m_n_borrowed_arenas
(Gauge) Effectively m_arena_first_register_count minus m_arena_last_deregister_count.
std::atomic< uint64_t > m_mapped_sz_hi_wmark
Max of m_mapped_sz observed so far.
std::atomic< uint64_t > m_n_borrowed_arenas_hi_wmark
Max of m_n_borrowed_arenas observed so far.
std::atomic< uint64_t > m_pool_register_count
Analogous to m_arena_register_count but counts individual in-arena SHM-pools.
std::atomic< uint64_t > m_mapped_sz
(Gauge) The combined vaddr-space, in bytes, across the SHM-pools counted in m_n_open_pools (modulo co...
std::atomic< uint64_t > m_n_open_pools_hi_wmark
Max of m_n_open_pools observed so far.
std::atomic< uint64_t > m_arena_register_count
How many times an arena was borrowed (opposing user did S.lend_arena(X)), including when already-bein...
std::atomic< uint64_t > m_pool_open_count
Analogous to m_arena_first_register_count but counts individual in-arena SHM-pools.
std::atomic< uint64_t > m_arena_first_register_count
Of the borrowings counted by m_arena_register_count, exclude those wherein arena was borrowed while a...