1pub(crate) mod stale_resource_cleanup;
201
202pub mod builder;
204
205pub mod dynamic_config;
207
208pub mod header;
211
212pub mod messaging_pattern;
215
216pub mod port_factory;
219
220pub mod service_name;
222
223pub mod service_id;
225
226pub mod static_config;
233
234pub mod attribute;
236
237pub mod local;
239
240pub mod local_threadsafe;
244
245pub mod ipc;
247
248pub mod ipc_threadsafe;
252
253pub(crate) mod config_scheme;
254pub(crate) mod naming_scheme;
255
256use alloc::sync::Arc;
257use core::fmt::Debug;
258use core::time::Duration;
259
260use crate::config;
261use crate::constants::MAX_TYPE_NAME_LENGTH;
262use crate::node::{NodeId, NodeListFailure, NodeState, SharedNode};
263use crate::service::config_scheme::dynamic_config_storage_config;
264use crate::service::dynamic_config::DynamicConfig;
265use crate::service::static_config::*;
266use config_scheme::service_tag_config;
267use iceoryx2_bb_container::semantic_string::SemanticString;
268use iceoryx2_bb_elementary::CallbackProgression;
269use iceoryx2_bb_log::{debug, fail, trace, warn};
270use iceoryx2_cal::arc_sync_policy::ArcSyncPolicy;
271use iceoryx2_cal::dynamic_storage::{
272 DynamicStorage, DynamicStorageBuilder, DynamicStorageOpenError,
273};
274use iceoryx2_cal::event::Event;
275use iceoryx2_cal::hash::*;
276use iceoryx2_cal::monitoring::Monitoring;
277use iceoryx2_cal::named_concept::NamedConceptListError;
278use iceoryx2_cal::named_concept::*;
279use iceoryx2_cal::reactor::Reactor;
280use iceoryx2_cal::resizable_shared_memory::ResizableSharedMemoryForPoolAllocator;
281use iceoryx2_cal::serialize::Serialize;
282use iceoryx2_cal::shared_memory::{SharedMemory, SharedMemoryForPoolAllocator};
283use iceoryx2_cal::shm_allocator::bump_allocator::BumpAllocator;
284use iceoryx2_cal::static_storage::*;
285use iceoryx2_cal::zero_copy_connection::ZeroCopyConnection;
286use service_id::ServiceId;
287
288use self::dynamic_config::DeregisterNodeState;
289use self::messaging_pattern::MessagingPattern;
290use self::service_name::ServiceName;
291
292#[derive(Debug, Clone, Copy, PartialEq, Eq)]
293pub enum ServiceRemoveNodeError {
295 VersionMismatch,
298 InternalError,
300 ServiceInCorruptedState,
303}
304
305#[derive(Debug, Clone, Copy, PartialEq, Eq)]
306pub(crate) enum ServiceRemoveTagError {
307 AlreadyRemoved,
308 InternalError,
309 InsufficientPermissions,
310}
311
312#[derive(Debug, Clone, Copy, PartialEq, Eq)]
314pub enum ServiceDetailsError {
315 FailedToOpenStaticServiceInfo,
317 FailedToReadStaticServiceInfo,
319 FailedToDeserializeStaticServiceInfo,
322 ServiceInInconsistentState,
324 VersionMismatch,
326 InternalError,
328 FailedToAcquireNodeState,
330}
331
332impl core::fmt::Display for ServiceDetailsError {
333 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
334 write!(f, "ServiceDetailsError::{self:?}")
335 }
336}
337
338impl core::error::Error for ServiceDetailsError {}
339
340#[derive(Debug, Clone, Copy, PartialEq, Eq)]
342pub enum ServiceListError {
343 InsufficientPermissions,
345 InternalError,
347}
348
349impl core::fmt::Display for ServiceListError {
350 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
351 write!(f, "ServiceListError::{self:?}")
352 }
353}
354
355impl core::error::Error for ServiceListError {}
356
357#[derive(Debug, Clone)]
360pub struct ServiceDynamicDetails<S: Service> {
361 pub nodes: Vec<NodeState<S>>,
363}
364
365#[derive(Debug)]
367pub struct ServiceDetails<S: Service> {
368 pub static_details: StaticConfig,
371 pub dynamic_details: Option<ServiceDynamicDetails<S>>,
373}
374
375#[derive(Debug)]
377pub struct ServiceState<S: Service, R: ServiceResource> {
378 pub(crate) dynamic_storage: S::DynamicStorage,
383 pub(crate) additional_resource: R,
385 pub(crate) static_config: StaticConfig,
386 pub(crate) shared_node: Arc<SharedNode<S>>,
387 pub(crate) static_storage: S::StaticStorage,
391}
392
393impl<S: Service, R: ServiceResource> ServiceState<S, R> {
394 pub(crate) fn new(
395 static_config: StaticConfig,
396 shared_node: Arc<SharedNode<S>>,
397 dynamic_storage: S::DynamicStorage,
398 static_storage: S::StaticStorage,
399 additional_resource: R,
400 ) -> Self {
401 let new_self = Self {
402 static_config,
403 shared_node,
404 dynamic_storage,
405 static_storage,
406 additional_resource,
407 };
408 trace!(from "Service::open()", "open service: {} ({:?})",
409 new_self.static_config.name(), new_self.static_config.service_id());
410 new_self
411 }
412}
413
414impl<S: Service, R: ServiceResource> Drop for ServiceState<S, R> {
415 fn drop(&mut self) {
416 let origin = "ServiceState::drop()";
417 let id = self.static_config.service_id();
418 self.shared_node.registered_services().remove(id, |handle| {
419 if let Err(e) = remove_service_tag::<S>(self.shared_node.id(), id, self.shared_node.config())
420 {
421 debug!(from origin, "The service tag could not be removed from the node {:?} ({:?}).",
422 self.shared_node.id(), e);
423 }
424
425 match self.dynamic_storage.get().deregister_node_id(handle) {
426 DeregisterNodeState::HasOwners => {
427 trace!(from origin, "close service: {} ({:?})",
428 self.static_config.name(), id);
429 }
430 DeregisterNodeState::NoMoreOwners => {
431 self.static_storage.acquire_ownership();
432 self.dynamic_storage.acquire_ownership();
433 self.additional_resource.acquire_ownership();
434 trace!(from origin, "close and remove service: {} ({:?})",
435 self.static_config.name(), id);
436 }
437 }
438 });
439 }
440}
441
442#[doc(hidden)]
443pub mod internal {
444 use builder::event::EventOpenError;
445 use dynamic_config::{PortCleanupAction, RemoveDeadNodeResult};
446 use iceoryx2_bb_container::byte_string::FixedSizeByteString;
447 use iceoryx2_bb_log::error;
448 use port_factory::PortFactory;
449
450 use crate::{
451 node::{NodeBuilder, NodeId},
452 port::{
453 listener::remove_connection_of_listener, notifier::Notifier,
454 port_identifiers::UniquePortId,
455 },
456 prelude::EventId,
457 service::stale_resource_cleanup::{
458 remove_data_segment_of_port, remove_receiver_port_from_all_connections,
459 remove_sender_port_from_all_connections,
460 },
461 };
462
463 use super::*;
464
465 #[derive(Debug)]
466 struct CleanupFailure;
467
468 fn send_dead_node_signal<S: Service>(service_id: &ServiceId, config: &config::Config) {
469 let origin = "send_dead_node_signal()";
470
471 let service_details = match details::<S>(config, &service_id.0.clone().into()) {
472 Ok(Some(service_details)) => service_details,
473 Ok(None) => return,
474 Err(e) => {
475 warn!(from origin,
476 "Unable to acquire service details to emit dead node signal to waiting listeners for the service id {:?} due to ({:?})",
477 service_id, e);
478 return;
479 }
480 };
481
482 let service_name = service_details.static_details.name();
483
484 let mut config = config.clone();
485 config.global.node.cleanup_dead_nodes_on_creation = false;
486 config.global.node.cleanup_dead_nodes_on_destruction = false;
487
488 let node = match NodeBuilder::new().config(&config).create::<S>() {
489 Ok(node) => node,
490 Err(e) => {
491 warn!(from origin,
492 "Unable to create node to emit dead node signal to waiting listeners on the service {} due to ({:?}).",
493 service_name, e);
494 return;
495 }
496 };
497
498 let service = match node.service_builder(service_name).event().open() {
499 Ok(service) => service,
500 Err(EventOpenError::DoesNotExist) => return,
501 Err(e) => {
502 warn!(from origin,
503 "Unable to open event service to emit dead node signal to waiting listeners on the service {} due to ({:?}).",
504 service_name, e);
505 return;
506 }
507 };
508
509 if service.dynamic_config().number_of_listeners() == 0 {
510 return;
511 }
512
513 let event_id = match service.static_config().notifier_dead_event {
514 Some(event_id) => event_id,
515 None => return,
516 };
517
518 let notifier = match Notifier::new_without_auto_event_emission(
519 service.service,
520 EventId::new(0),
521 ) {
522 Ok(notifier) => notifier,
523 Err(e) => {
524 warn!(from origin,
525 "Unable to create notifier to send dead node signal to waiting listeners on the service {} due to ({:?})",
526 service_name, e);
527 return;
528 }
529 };
530
531 if let Err(e) = notifier.notify_with_custom_event_id(EventId::new(event_id)) {
532 warn!(from origin,
533 "Unable to send dead node signal to waiting listeners on service {} due to ({:?})",
534 service_name, e);
535 }
536
537 trace!(from origin, "Send dead node signal on service {}.", service_name);
538 }
539
540 fn remove_sender_connection_and_data_segment<S: Service>(
541 id: u128,
542 config: &config::Config,
543 origin: &str,
544 port_name: &str,
545 ) -> Result<(), CleanupFailure> {
546 unsafe { remove_sender_port_from_all_connections::<S>(id, config) }.map_err(|e| {
547 debug!(from origin,
548 "Failed to remove the {} ({:?}) from all of its connections ({:?}).",
549 port_name, id, e);
550 CleanupFailure
551 })?;
552
553 unsafe { remove_data_segment_of_port::<S>(id, config) }.map_err(|e| {
554 debug!(from origin,
555 "Failed to remove the {} ({:?}) data segment ({:?}).",
556 port_name, id, e);
557 CleanupFailure
558 })?;
559
560 Ok(())
561 }
562
563 fn remove_sender_and_receiver_connections_and_data_segment<S: Service>(
564 id: u128,
565 config: &config::Config,
566 origin: &str,
567 port_name: &str,
568 ) -> Result<(), CleanupFailure> {
569 remove_sender_connection_and_data_segment::<S>(id, config, origin, port_name)?;
570 unsafe { remove_receiver_port_from_all_connections::<S>(id, config) }.map_err(|e| {
571 debug!(from origin,
572 "Failed to remove the {} ({:?}) from all of its incoming connections ({:?}).",
573 port_name, id, e);
574 CleanupFailure
575 })?;
576
577 Ok(())
578 }
579
580 fn remove_additional_blackboard_resources<S: Service>(
581 config: &config::Config,
582 blackboard_name: &FileName,
583 blackboard_payload_config: &<S::BlackboardPayload as NamedConceptMgmt>::Configuration,
584 blackboard_mgmt_name: &FixedSizeByteString<MAX_TYPE_NAME_LENGTH>,
585 origin: &str,
586 msg: &str,
587 ) {
588 match unsafe {
589 <S::BlackboardPayload as NamedConceptMgmt>::remove_cfg(
590 blackboard_name,
591 blackboard_payload_config,
592 )
593 } {
594 Ok(true) => {
595 trace!(from origin, "Remove blackboard payload segment.");
596 }
597 _ => {
598 error!(from origin,
599 "{} since the blackboard payload segment cannot be removed - service seems to be in a corrupted state.", msg);
600 }
601 }
602
603 match blackboard_mgmt_name.as_str() {
604 Ok(s) => {
605 let mut blackboard_mgmt_config =
608 crate::service::config_scheme::blackboard_mgmt_config::<S, u64>(config);
609 unsafe {
612 <S::BlackboardMgmt<u64> as DynamicStorage::<u64>>::__internal_set_type_name_in_config(
613 &mut blackboard_mgmt_config,
614 s
615 )
616 };
617 match unsafe {
618 <S::BlackboardMgmt<u64> as NamedConceptMgmt>::remove_cfg(
619 blackboard_name,
620 &blackboard_mgmt_config,
621 )
622 } {
623 Ok(true) => {
624 trace!(from origin, "Remove blackboard mgmt segment.");
625 }
626 _ => {
627 error!(from origin,
628 "{} since the blackboard mgmt segment cannot be removed - service seems to be in a corrupted state.", msg);
629 }
630 }
631 }
632 Err(_) => {
633 error!(from origin, "{} since the blackboard mgmt segment name cannot be acquired.", msg);
634 }
635 }
636 }
637
638 pub trait ServiceInternal<S: Service> {
639 fn __internal_remove_node_from_service(
640 node_id: &NodeId,
641 service_id: &ServiceId,
642 config: &config::Config,
643 ) -> Result<(), ServiceRemoveNodeError> {
644 let origin = format!("Service::remove_node_from_service({node_id:?}, {service_id:?})");
645 let msg = "Unable to remove node from service";
646
647 let dynamic_config = match open_dynamic_config::<S>(config, service_id) {
648 Ok(Some(c)) => c,
649 Ok(None) => {
650 fail!(from origin,
651 with ServiceRemoveNodeError::ServiceInCorruptedState,
652 "{} since the dynamic service segment is missing - service seems to be in a corrupted state.", msg);
653 }
654 Err(ServiceDetailsError::VersionMismatch) => {
655 fail!(from origin, with ServiceRemoveNodeError::VersionMismatch,
656 "{} since the service version does not match.", msg);
657 }
658 Err(e) => {
659 fail!(from origin, with ServiceRemoveNodeError::InternalError,
660 "{} due to an internal failure ({:?}).", msg, e);
661 }
662 };
663
664 let mut number_of_dead_node_notifications = 0;
665 let cleanup_port_resources = |port_id| {
666 match port_id {
667 UniquePortId::Publisher(ref id) => {
668 if remove_sender_connection_and_data_segment::<S>(
669 id.value(),
670 config,
671 &origin,
672 "publisher",
673 )
674 .is_err()
675 {
676 return PortCleanupAction::SkipPort;
677 }
678 }
679 UniquePortId::Subscriber(ref id) => {
680 if let Err(e) = unsafe {
681 remove_receiver_port_from_all_connections::<S>(id.value(), config)
682 } {
683 debug!(from origin, "Failed to remove the subscriber ({:?}) from all of its connections ({:?}).", id, e);
684 return PortCleanupAction::SkipPort;
685 }
686 }
687 UniquePortId::Notifier(_) => {
688 number_of_dead_node_notifications += 1;
689 }
690 UniquePortId::Listener(ref id) => {
691 if let Err(e) = unsafe { remove_connection_of_listener::<S>(id, config) } {
692 debug!(from origin, "Failed to remove the listeners ({:?}) connection ({:?}).", id, e);
693 return PortCleanupAction::SkipPort;
694 }
695 }
696 UniquePortId::Client(ref id) => {
697 if remove_sender_and_receiver_connections_and_data_segment::<S>(
698 id.value(),
699 config,
700 &origin,
701 "client",
702 )
703 .is_err()
704 {
705 return PortCleanupAction::SkipPort;
706 }
707 }
708 UniquePortId::Server(ref id) => {
709 if remove_sender_and_receiver_connections_and_data_segment::<S>(
710 id.value(),
711 config,
712 &origin,
713 "server",
714 )
715 .is_err()
716 {
717 return PortCleanupAction::SkipPort;
718 }
719 }
720 UniquePortId::Reader(ref _id) => {}
721 UniquePortId::Writer(ref _id) => {}
722 };
723
724 trace!(from origin, "Remove port {:?} from service.", port_id);
725 PortCleanupAction::RemovePort
726 };
727
728 let remove_service = match unsafe {
729 dynamic_config
730 .get()
731 .remove_dead_node_id(node_id, cleanup_port_resources)
732 } {
733 Ok(DeregisterNodeState::HasOwners) => false,
734 Ok(DeregisterNodeState::NoMoreOwners) => true,
735 Err(RemoveDeadNodeResult::NodeNotRegistered) => {
736 dynamic_config.get().is_marked_for_destruction()
737 }
738 };
739
740 if remove_service {
741 let blackboard_name =
743 crate::service::naming_scheme::blackboard_name(service_id.as_str());
744 let blackboard_payload_config =
745 crate::service::config_scheme::blackboard_data_config::<S>(config);
746 let blackboard_payload = <S::BlackboardPayload as NamedConceptMgmt>::does_exist_cfg(
747 &blackboard_name,
748 &blackboard_payload_config,
749 );
750 let mut is_blackboard = false;
751 let mut blackboard_mgmt_name = FixedSizeByteString::<MAX_TYPE_NAME_LENGTH>::new();
752 if let Ok(true) = blackboard_payload {
753 is_blackboard = true;
754
755 let details = match details::<S>(config, &service_id.0.clone().into()) {
756 Ok(Some(d)) => d,
757 _ => {
758 fail!(from origin,
759 with ServiceRemoveNodeError::ServiceInCorruptedState,
760 "{} due to a failure while acquiring the service details.", msg);
761 }
762 };
763 blackboard_mgmt_name =
764 details.static_details.blackboard().type_details.type_name;
765 }
766
767 match unsafe {
768 remove_static_service_config::<S>(config, &service_id.0.clone().into())
772 } {
773 Ok(_) => {
774 trace!(from origin, "Remove unused service.");
775
776 if is_blackboard {
778 remove_additional_blackboard_resources::<S>(
779 config,
780 &blackboard_name,
781 &blackboard_payload_config,
782 &blackboard_mgmt_name,
783 &origin,
784 msg,
785 );
786 }
787
788 dynamic_config.acquire_ownership()
789 }
790 Err(e) => {
791 error!(from origin, "Unable to remove static config of unused service ({:?}).",
792 e);
793 }
794 }
795 } else if number_of_dead_node_notifications != 0 {
796 send_dead_node_signal::<S>(service_id, config);
797 }
798
799 Ok(())
800 }
801 }
802}
803
804pub trait ServiceResource {
807 fn acquire_ownership(&self);
810}
811
812#[derive(Debug)]
813pub(crate) struct NoResource;
814impl ServiceResource for NoResource {
815 fn acquire_ownership(&self) {}
816}
817
818#[allow(private_bounds)]
823pub trait Service: Debug + Sized + internal::ServiceInternal<Self> + Clone {
824 type ServiceNameHasher: Hash;
827
828 type StaticStorage: StaticStorage;
830
831 type ConfigSerializer: Serialize;
833
834 type DynamicStorage: DynamicStorage<DynamicConfig>;
837
838 type SharedMemory: SharedMemoryForPoolAllocator;
840
841 type ResizableSharedMemory: ResizableSharedMemoryForPoolAllocator<Self::SharedMemory>;
843
844 type Connection: ZeroCopyConnection;
846
847 type Event: Event;
849
850 type Monitoring: Monitoring;
852
853 type Reactor: Reactor;
855
856 type ArcThreadSafetyPolicy<T: Send + Debug>: ArcSyncPolicy<T>;
863
864 type BlackboardMgmt<T: Send + Sync + Debug + 'static>: DynamicStorage<T>;
866
867 type BlackboardPayload: SharedMemory<BumpAllocator>;
869
870 fn does_exist(
889 service_name: &ServiceName,
890 config: &config::Config,
891 messaging_pattern: MessagingPattern,
892 ) -> Result<bool, ServiceDetailsError> {
893 Ok(Self::details(service_name, config, messaging_pattern)?.is_some())
894 }
895
896 fn details(
919 service_name: &ServiceName,
920 config: &config::Config,
921 messaging_pattern: MessagingPattern,
922 ) -> Result<Option<ServiceDetails<Self>>, ServiceDetailsError> {
923 let service_id = ServiceId::new::<Self::ServiceNameHasher>(service_name, messaging_pattern);
924 details::<Self>(config, &service_id.0.into())
925 }
926
927 fn list<F: FnMut(ServiceDetails<Self>) -> CallbackProgression>(
944 config: &config::Config,
945 mut callback: F,
946 ) -> Result<(), ServiceListError> {
947 let msg = "Unable to list all services";
948 let origin = "Service::list_from_config()";
949 let static_storage_config = config_scheme::static_config_storage_config::<Self>(config);
950
951 let service_uuids = fail!(from origin,
952 when <Self::StaticStorage as NamedConceptMgmt>::list_cfg(&static_storage_config),
953 map NamedConceptListError::InsufficientPermissions => ServiceListError::InsufficientPermissions,
954 unmatched ServiceListError::InternalError,
955 "{} due to a failure while collecting all active services for config: {:?}", msg, config);
956
957 for uuid in &service_uuids {
958 if let Ok(Some(service_details)) = details::<Self>(config, uuid) {
959 if callback(service_details) == CallbackProgression::Stop {
960 break;
961 }
962 }
963 }
964
965 Ok(())
966 }
967}
968
969pub(crate) unsafe fn remove_static_service_config<S: Service>(
970 config: &config::Config,
971 uuid: &FileName,
972) -> Result<bool, NamedConceptRemoveError> {
973 let msg = "Unable to remove static service config";
974 let origin = "Service::remove_static_service_config()";
975 let static_storage_config = config_scheme::static_config_storage_config::<S>(config);
976
977 match <S::StaticStorage as NamedConceptMgmt>::remove_cfg(uuid, &static_storage_config) {
978 Ok(v) => Ok(v),
979 Err(e) => {
980 fail!(from origin, with e, "{msg} due to ({:?}).", e);
981 }
982 }
983}
984
985fn details<S: Service>(
986 config: &config::Config,
987 uuid: &FileName,
988) -> Result<Option<ServiceDetails<S>>, ServiceDetailsError> {
989 let msg = "Unable to acquire service details";
990 let origin = "Service::details()";
991 let static_storage_config = config_scheme::static_config_storage_config::<S>(config);
992
993 let reader = match <<S::StaticStorage as StaticStorage>::Builder as NamedConceptBuilder<
994 S::StaticStorage,
995 >>::new(uuid)
996 .config(&static_storage_config.clone())
997 .has_ownership(false)
998 .open(Duration::ZERO)
999 {
1000 Ok(reader) => reader,
1001 Err(StaticStorageOpenError::DoesNotExist)
1002 | Err(StaticStorageOpenError::InitializationNotYetFinalized) => return Ok(None),
1003 Err(e) => {
1004 fail!(from origin, with ServiceDetailsError::FailedToOpenStaticServiceInfo,
1005 "{} due to a failure while opening the static service info \"{}\" for reading ({:?})",
1006 msg, uuid, e);
1007 }
1008 };
1009
1010 let mut content = String::from_utf8(vec![b' '; reader.len() as usize]).unwrap();
1011 if let Err(e) = reader.read(unsafe { content.as_mut_vec().as_mut_slice() }) {
1012 fail!(from origin, with ServiceDetailsError::FailedToReadStaticServiceInfo,
1013 "{} since the static service info \"{}\" could not be read ({:?}).",
1014 msg, uuid, e );
1015 }
1016
1017 let service_config =
1018 match S::ConfigSerializer::deserialize::<StaticConfig>(unsafe { content.as_mut_vec() }) {
1019 Ok(service_config) => service_config,
1020 Err(e) => {
1021 fail!(from origin, with ServiceDetailsError::FailedToDeserializeStaticServiceInfo,
1022 "{} since the static service info \"{}\" could not be deserialized ({:?}).",
1023 msg, uuid, e );
1024 }
1025 };
1026
1027 if uuid.as_bytes() != service_config.service_id().0.as_bytes() {
1028 fail!(from origin, with ServiceDetailsError::ServiceInInconsistentState,
1029 "{} since the service {:?} has an inconsistent hash of {} according to config {:?}",
1030 msg, service_config, uuid, config);
1031 }
1032
1033 let dynamic_config = open_dynamic_config::<S>(config, service_config.service_id())?;
1034 let dynamic_details = if let Some(d) = dynamic_config {
1035 let mut nodes = vec![];
1036 d.get().list_node_ids(|node_id| {
1037 match NodeState::new(node_id, config) {
1038 Ok(Some(state)) => nodes.push(state),
1039 Ok(None)
1040 | Err(NodeListFailure::InsufficientPermissions)
1041 | Err(NodeListFailure::Interrupt) => (),
1042 Err(NodeListFailure::InternalError) => {
1043 debug!(from origin, "Unable to acquire NodeState for service \"{:?}\"", uuid);
1044 }
1045 };
1046 CallbackProgression::Continue
1047 });
1048 Some(ServiceDynamicDetails { nodes })
1049 } else {
1050 None
1051 };
1052
1053 Ok(Some(ServiceDetails {
1054 static_details: service_config,
1055 dynamic_details,
1056 }))
1057}
1058
1059fn open_dynamic_config<S: Service>(
1060 config: &config::Config,
1061 service_id: &ServiceId,
1062) -> Result<Option<S::DynamicStorage>, ServiceDetailsError> {
1063 let origin = format!(
1064 "Service::open_dynamic_details<{}>({:?})",
1065 core::any::type_name::<S>(),
1066 service_id
1067 );
1068 let msg = "Unable to open the services dynamic config";
1069 match
1070 <<S::DynamicStorage as DynamicStorage<
1071 DynamicConfig,
1072 >>::Builder<'_> as NamedConceptBuilder<
1073 S::DynamicStorage,
1074 >>::new(&service_id.0.clone().into())
1075 .config(&dynamic_config_storage_config::<S>(config))
1076 .has_ownership(false)
1077 .open() {
1078 Ok(storage) => Ok(Some(storage)),
1079 Err(DynamicStorageOpenError::DoesNotExist) | Err(DynamicStorageOpenError::InitializationNotYetFinalized) => Ok(None),
1080 Err(DynamicStorageOpenError::VersionMismatch) => {
1081 fail!(from origin, with ServiceDetailsError::VersionMismatch,
1082 "{} since there is a version mismatch. Please use the same iceoryx2 version for the whole system.", msg);
1083 }
1084 Err(DynamicStorageOpenError::InternalError) => {
1085 fail!(from origin, with ServiceDetailsError::InternalError,
1086 "{} due to an internal failure while opening the services dynamic config.", msg);
1087 }
1088 }
1089}
1090
1091pub(crate) fn remove_service_tag<S: Service>(
1092 node_id: &NodeId,
1093 service_id: &ServiceId,
1094 config: &config::Config,
1095) -> Result<(), ServiceRemoveTagError> {
1096 let origin = format!(
1097 "remove_service_tag<{}>({:?}, service_id: {:?})",
1098 core::any::type_name::<S>(),
1099 node_id,
1100 service_id
1101 );
1102
1103 match unsafe {
1104 <S::StaticStorage as NamedConceptMgmt>::remove_cfg(
1105 &service_id.0.clone().into(),
1106 &service_tag_config::<S>(config, node_id),
1107 )
1108 } {
1109 Ok(true) => Ok(()),
1110 Ok(false) => {
1111 fail!(from origin, with ServiceRemoveTagError::AlreadyRemoved,
1112 "The service's tag for the node was already removed. This may indicate a corrupted system!");
1113 }
1114 Err(NamedConceptRemoveError::InternalError) => {
1115 fail!(from origin, with ServiceRemoveTagError::InternalError,
1116 "Unable to remove the service's tag for the node due to an internal error.");
1117 }
1118 Err(NamedConceptRemoveError::InsufficientPermissions) => {
1119 fail!(from origin, with ServiceRemoveTagError::InsufficientPermissions,
1120 "Unable to remove the service's tag for the node due to insufficient permissions.");
1121 }
1122 }
1123}