zenoh_shm/api/client_storage/
mod.rs

1//
2// Copyright (c) 2023 ZettaScale Technology
3//
4// This program and the accompanying materials are made available under the
5// terms of the Eclipse Public License 2.0 which is available at
6// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
7// which is available at https://www.apache.org/licenses/LICENSE-2.0.
8//
9// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
10//
11// Contributors:
12//   ZettaScale Zenoh Team, <zenoh@zettascale.tech>
13//
14
15use std::{
16    collections::BTreeMap,
17    sync::{Arc, RwLock},
18};
19
20use static_init::dynamic;
21use zenoh_result::{bail, ZResult};
22
23use crate::{
24    api::{
25        client::{shm_client::ShmClient, shm_segment::ShmSegment},
26        common::{types::ProtocolID, with_id::WithProtocolID},
27        protocol_implementations::posix::posix_shm_client::PosixShmClient,
28    },
29    reader::{ClientStorage, GlobalDataSegmentId},
30};
31
32#[dynamic(lazy, drop)]
33/// A global lazily-initialized SHM client storage. When initialized,
34/// contains default client set, see [with_default_client_set](ShmClientStorage::with_default_client_set)
35#[zenoh_macros::unstable_doc]
36pub static mut GLOBAL_CLIENT_STORAGE: Arc<ShmClientStorage> = Arc::new(
37    ShmClientStorage::builder()
38        .with_default_client_set()
39        .build(),
40);
41
42/// Builder to create new client storages
43#[zenoh_macros::unstable_doc]
44pub struct ShmClientSetBuilder;
45
46impl ShmClientSetBuilder {
47    /// Add client to the storage (without including the default client set)
48    #[zenoh_macros::unstable_doc]
49    pub fn with_client(self, client: Arc<dyn ShmClient>) -> ShmClientStorageBuilder {
50        let clients = BTreeMap::from([(client.id(), client)]);
51        ShmClientStorageBuilder::new(clients)
52    }
53
54    /// Add list of clients to the storage (without including the default client set)
55    #[zenoh_macros::unstable_doc]
56    pub fn with_clients(self, clients: &[Arc<dyn ShmClient>]) -> ShmClientStorageBuilder {
57        let clients = clients
58            .iter()
59            .cloned()
60            .map(|client| (client.id(), client))
61            .collect();
62        ShmClientStorageBuilder::new(clients)
63    }
64
65    /// Include default clients
66    #[zenoh_macros::unstable_doc]
67    pub fn with_default_client_set(self) -> ShmClientStorageBuilder {
68        let client = PosixShmClient {};
69        let clients = BTreeMap::from([(client.id(), Arc::new(client) as Arc<dyn ShmClient>)]);
70        ShmClientStorageBuilder::new(clients)
71    }
72}
73
74#[zenoh_macros::unstable_doc]
75pub struct ShmClientStorageBuilder {
76    clients: BTreeMap<ProtocolID, Arc<dyn ShmClient>>,
77}
78
79impl ShmClientStorageBuilder {
80    fn new(clients: BTreeMap<ProtocolID, Arc<dyn ShmClient>>) -> Self {
81        Self { clients }
82    }
83
84    /// Add client to the storage
85    #[zenoh_macros::unstable_doc]
86    pub fn with_client(mut self, client: Arc<dyn ShmClient>) -> ZResult<Self> {
87        let id = client.id();
88        match self.clients.entry(id) {
89            std::collections::btree_map::Entry::Occupied(occupied) => {
90                bail!("Client already exists for id {id}: {:?}!", occupied)
91            }
92            std::collections::btree_map::Entry::Vacant(vacant) => {
93                vacant.insert(client as Arc<dyn ShmClient>);
94                Ok(self)
95            }
96        }
97    }
98
99    /// Add list of clients to the storage
100    #[zenoh_macros::unstable_doc]
101    pub fn with_clients(mut self, clients: &[Arc<dyn ShmClient>]) -> Self {
102        self.clients
103            .extend(clients.iter().cloned().map(|client| (client.id(), client)));
104        self
105    }
106
107    /// Build the storage with parameters specified on previous step
108    #[zenoh_macros::unstable_doc]
109    pub fn build(self) -> ShmClientStorage {
110        ShmClientStorage::new(self.clients)
111    }
112}
113
114/// A storage for SHM clients.
115/// Runtime or Session constructed with instance of this type gets capabilities to read
116/// SHM buffers for Protocols added to this instance.
117#[zenoh_macros::unstable_doc]
118#[derive(Debug)]
119pub struct ShmClientStorage {
120    pub(crate) clients: ClientStorage<Arc<dyn ShmClient>>,
121    pub(crate) segments: RwLock<BTreeMap<GlobalDataSegmentId, Arc<dyn ShmSegment>>>,
122}
123
124impl Eq for ShmClientStorage {}
125
126impl PartialEq for ShmClientStorage {
127    fn eq(&self, other: &Self) -> bool {
128        std::ptr::eq(self, other)
129    }
130}
131
132impl ShmClientStorage {
133    /// Get the builder to construct a new storage
134    #[zenoh_macros::unstable_doc]
135    pub fn builder() -> ShmClientSetBuilder {
136        ShmClientSetBuilder
137    }
138
139    /// Get the list of supported SHM protocols.
140    #[zenoh_macros::unstable_doc]
141    pub fn supported_protocols(&self) -> Vec<ProtocolID> {
142        self.clients.get_clients().keys().copied().collect()
143    }
144
145    fn new(clients: BTreeMap<ProtocolID, Arc<dyn ShmClient>>) -> Self {
146        Self {
147            clients: ClientStorage::new(clients),
148            segments: RwLock::default(),
149        }
150    }
151}