1pub(crate) mod global_management_segment;
143pub mod node_name;
145
146use core::fmt::Debug;
147use core::marker::PhantomData;
148use core::ptr::NonNull;
149use core::time::Duration;
150use iceoryx2_bb_concurrency::atomic::Ordering;
151
152use alloc::collections::BTreeMap;
153use alloc::format;
154use alloc::string::String;
155use alloc::string::ToString;
156use alloc::sync::Arc;
157use alloc::vec;
158use alloc::vec::Vec;
159
160use iceoryx2_bb_concurrency::atomic::AtomicBool;
161use iceoryx2_bb_concurrency::cell::UnsafeCell;
162use iceoryx2_bb_container::semantic_string::SemanticString;
163use iceoryx2_bb_derive_macros::ZeroCopySend;
164use iceoryx2_bb_elementary::CallbackProgression;
165use iceoryx2_bb_elementary::scope_guard::ScopeGuardBuilder;
166use iceoryx2_bb_elementary_traits::testing::abandonable::Abandonable;
167use iceoryx2_bb_elementary_traits::zero_copy_send::ZeroCopySend;
168use iceoryx2_bb_posix::adaptive_wait::{AdaptiveWaitBuilder, AdaptiveWaitStrategy};
169use iceoryx2_bb_posix::clock::Time;
170use iceoryx2_bb_posix::clock::{NanosleepError, nanosleep};
171use iceoryx2_bb_posix::mutex::Handle;
172use iceoryx2_bb_posix::mutex::Mutex;
173use iceoryx2_bb_posix::mutex::MutexBuilder;
174use iceoryx2_bb_posix::mutex::MutexHandle;
175use iceoryx2_bb_posix::mutex::MutexType;
176use iceoryx2_bb_posix::process::Process;
177use iceoryx2_bb_posix::process::ProcessId;
178use iceoryx2_bb_posix::signal::SignalHandler;
179use iceoryx2_bb_system_types::file_name::FileName;
180use iceoryx2_cal::bag::BagFamily;
181use iceoryx2_cal::bag::BagHandleFamily;
182use iceoryx2_cal::named_concept::{NamedConceptPathHintRemoveError, NamedConceptRemoveError};
183use iceoryx2_cal::{
184 monitoring::*, named_concept::NamedConceptListError, serialize::*, static_storage::*,
185};
186use iceoryx2_log::{debug, fail, fatal_panic, trace, warn};
187
188use crate::identifiers::UniqueNodeId;
189use crate::node::node_name::NodeName;
190use crate::prelude::MessagingPattern;
191use crate::service::ServiceRemoveError;
192use crate::service::builder::{Builder, OpenDynamicStorageFailure};
193use crate::service::config_scheme::port_tag_config;
194use crate::service::config_scheme::{
195 node_details_path, node_monitoring_config, service_tag_config,
196};
197use crate::service::service_hash::ServiceHash;
198use crate::service::service_name::ServiceName;
199use crate::service::stale_resource_cleanup::RemoveStalePortResourcesError;
200use crate::service::stale_resource_cleanup::remove_stale_port_resources;
201use crate::service::{self, ServiceRemoveNodeError};
202use crate::signal_handling_mode::SignalHandlingMode;
203use crate::unique_id_generator::*;
204use crate::{config::Config, service::config_scheme::node_details_config};
205
206impl UniqueNodeId {
207 pub(crate) fn as_file_name(&self) -> FileName {
208 fatal_panic!(from self, when FileName::new(self.0.value().to_string().as_bytes()),
209 "This should never happen! The NodeId shall be always a valid FileName.")
210 }
211}
212
213#[derive(Debug, Copy, Clone, PartialEq, Eq)]
215pub enum NodeCreationFailure {
216 InsufficientPermissions,
218 InternalError,
220 SystemCorrupted,
222 UnableToGenerateUniqueNodeId,
224}
225
226impl core::fmt::Display for NodeCreationFailure {
227 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
228 write!(f, "NodeCreationFailure::{self:?}")
229 }
230}
231
232impl core::error::Error for NodeCreationFailure {}
233
234#[derive(Debug, Copy, Clone, PartialEq, Eq)]
236pub enum NodeWaitFailure {
237 Interrupt,
239 TerminationRequest,
241}
242
243impl core::fmt::Display for NodeWaitFailure {
244 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
245 write!(f, "NodeWaitFailure::{self:?}")
246 }
247}
248
249impl core::error::Error for NodeWaitFailure {}
250
251#[derive(Debug, Copy, Clone, PartialEq, Eq)]
253pub enum NodeListFailure {
254 InsufficientPermissions,
256 Interrupt,
258 InternalError,
260}
261
262impl core::fmt::Display for NodeListFailure {
263 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
264 write!(f, "NodeListFailure::{self:?}")
265 }
266}
267
268impl core::error::Error for NodeListFailure {}
269
270#[derive(Debug, Copy, Clone, PartialEq, Eq)]
273pub enum NodeCleanupFailure {
274 Interrupt,
276 InternalError,
278 InsufficientPermissions,
280 VersionMismatch,
282 ResourcesAlreadyCleanedUp,
284 AnotherInstanceIsCleaningUpTheNode,
286}
287
288impl core::fmt::Display for NodeCleanupFailure {
289 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
290 write!(f, "NodeCleanupFailure::{self:?}")
291 }
292}
293
294impl core::error::Error for NodeCleanupFailure {}
295
296#[derive(Debug, Copy, Clone, PartialEq, Eq)]
297enum NodeReadStorageFailure {
298 ReadError,
299 InsufficientPermissions,
300 Corrupted,
301 Interrupt,
302 InternalError,
303}
304
305#[derive(Debug, Copy, Clone, PartialEq, Eq)]
306enum NodeReadServiceTagsFailure {
307 InsufficientPermissions,
308 InternalError,
309}
310
311#[derive(Debug, Copy, Clone, PartialEq, Eq)]
312enum NodeReadPortTagsFailure {
313 InsufficientPermissions,
314 InternalError,
315}
316
317#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
320pub struct NodeDetails {
321 executable: FileName,
322 process: ProcessId,
323 name: NodeName,
324 config: Config,
325}
326
327impl NodeDetails {
328 #[doc(hidden)]
329 pub fn __internal_new(node_name: &Option<NodeName>, config: &Config) -> Self {
330 Self::new(node_name, config)
331 }
332
333 fn new(node_name: &Option<NodeName>, config: &Config) -> Self {
334 let process = Process::from_self();
335
336 let executable = match process.executable() {
337 Ok(n) => n.file_name(),
338 Err(e) => {
339 debug!(from "NodeDetails::new()", "Unable to acquire executable name of the Node's process ({:?}).", e);
340 const FALLBACK_EXEC: &[u8] = b"undefined";
341 unsafe { FileName::new_unchecked(FALLBACK_EXEC) }
342 }
343 };
344
345 Self {
346 executable,
347 process: process.id(),
348 name: if let Some(name) = node_name {
349 name.clone()
350 } else {
351 NodeName::new("").expect("An empty NodeName is always valid.")
352 },
353 config: config.clone(),
354 }
355 }
356
357 pub fn executable(&self) -> &FileName {
359 &self.executable
360 }
361
362 pub fn process_id(&self) -> ProcessId {
364 self.process
365 }
366
367 pub fn name(&self) -> &NodeName {
370 &self.name
371 }
372
373 pub fn config(&self) -> &Config {
375 &self.config
376 }
377}
378
379#[derive(Debug)]
382pub enum NodeState<Service: service::Service> {
383 Alive(AliveNodeView<Service>),
385 Dead(DeadNodeView<Service>),
388 Inaccessible(UniqueNodeId),
390 Undefined(UniqueNodeId),
394}
395
396impl<Service: service::Service> Clone for NodeState<Service> {
397 fn clone(&self) -> Self {
398 match self {
399 NodeState::Alive(n) => NodeState::Alive(n.clone()),
400 NodeState::Dead(n) => NodeState::Dead(n.clone()),
401 NodeState::Inaccessible(n) => NodeState::Inaccessible(*n),
402 NodeState::Undefined(n) => NodeState::Undefined(*n),
403 }
404 }
405}
406
407impl<Service: service::Service> NodeState<Service> {
408 pub(crate) fn new(
409 node_id: &UniqueNodeId,
410 config: &Config,
411 ) -> Result<Option<Self>, NodeListFailure> {
412 let details = Node::<Service>::get_node_details(config, node_id).unwrap_or_default();
413
414 let node_view = AliveNodeView::<Service> {
415 id: *node_id,
416 details,
417 _service: PhantomData,
418 };
419
420 match Node::<Service>::get_node_state(config, node_id) {
421 Ok(State::DoesNotExist) => Ok(None),
422 Ok(State::Alive) => Ok(Some(NodeState::Alive(node_view))),
423 Ok(State::Dead) => Ok(Some(NodeState::Dead(DeadNodeView(node_view)))),
424 Err(NodeListFailure::InsufficientPermissions) => {
425 Ok(Some(NodeState::Inaccessible(*node_id)))
426 }
427 Err(NodeListFailure::InternalError) => Ok(Some(NodeState::Undefined(*node_id))),
428 Err(e) => Err(e),
429 }
430 }
431
432 pub fn node_id(&self) -> &UniqueNodeId {
434 match self {
435 NodeState::Dead(node) => node.id(),
436 NodeState::Alive(node) => node.id(),
437 NodeState::Inaccessible(node_id) => node_id,
438 NodeState::Undefined(node_id) => node_id,
439 }
440 }
441}
442
443#[derive(Debug, Clone, Copy, PartialEq, Eq, ZeroCopySend)]
449#[repr(C)]
450pub struct CleanupState {
451 pub cleanups: u64,
453 pub failed_cleanups: u64,
455}
456
457pub trait NodeView {
459 fn id(&self) -> &UniqueNodeId;
461 fn details(&self) -> &Option<NodeDetails>;
463}
464
465#[derive(Debug)]
467pub struct AliveNodeView<Service: service::Service> {
468 id: UniqueNodeId,
469 details: Option<NodeDetails>,
470 _service: PhantomData<Service>,
471}
472
473impl<Service: service::Service> Clone for AliveNodeView<Service> {
474 fn clone(&self) -> Self {
475 Self {
476 id: self.id,
477 details: self.details.clone(),
478 _service: PhantomData,
479 }
480 }
481}
482
483impl<Service: service::Service> NodeView for AliveNodeView<Service> {
484 fn id(&self) -> &UniqueNodeId {
485 &self.id
486 }
487
488 fn details(&self) -> &Option<NodeDetails> {
489 &self.details
490 }
491}
492
493#[derive(Debug)]
495pub struct DeadNodeView<Service: service::Service>(AliveNodeView<Service>);
496
497impl<Service: service::Service> Clone for DeadNodeView<Service> {
498 fn clone(&self) -> Self {
499 Self(self.0.clone())
500 }
501}
502
503impl<Service: service::Service> NodeView for DeadNodeView<Service> {
504 fn id(&self) -> &UniqueNodeId {
505 self.0.id()
506 }
507
508 fn details(&self) -> &Option<NodeDetails> {
509 self.0.details()
510 }
511}
512
513impl<Service: service::Service> DeadNodeView<Service> {
514 #[doc(hidden)]
515 pub fn __internal_try_remove_stale_resources(
516 id: UniqueNodeId,
517 details: NodeDetails,
518 ) -> Result<(), NodeCleanupFailure> {
519 DeadNodeView(AliveNodeView {
520 id,
521 details: Some(details),
522 _service: PhantomData::<Service>,
523 })
524 .try_remove_stale_resources()
525 }
526
527 #[doc(hidden)]
528 pub fn __internal_blocking_remove_stale_resources(
529 id: UniqueNodeId,
530 details: NodeDetails,
531 timeout: Duration,
532 ) -> Result<(), NodeCleanupFailure> {
533 DeadNodeView(AliveNodeView {
534 id,
535 details: Some(details),
536 _service: PhantomData::<Service>,
537 })
538 .blocking_remove_stale_resources(timeout)
539 }
540
541 pub fn blocking_remove_stale_resources(
551 self,
552 timeout: Duration,
553 ) -> Result<(), NodeCleanupFailure> {
554 let msg = "Unable to block until the stale resources of the dead node are removed";
555 let mut adaptive_wait = fail!(from self,
556 when AdaptiveWaitBuilder::new()
557 .strategy(AdaptiveWaitStrategy::FixedTicks(Duration::from_millis(1)))
558 .create(),
559 with NodeCleanupFailure::InternalError,
560 "{msg} since the adaptive wait builder could not be initiated.");
561 let start = fail!(from self,
562 when Time::now(),
563 with NodeCleanupFailure::InternalError,
564 "{msg} since the current system time could not be acquired.");
565
566 loop {
567 match self.remove_stale_resources_impl() {
568 Ok(()) | Err(NodeCleanupFailure::ResourcesAlreadyCleanedUp) => return Ok(()),
569 Err(NodeCleanupFailure::AnotherInstanceIsCleaningUpTheNode) => (),
570 Err(e) => return Err(e),
571 }
572
573 fail!(from self,
574 when adaptive_wait.wait(),
575 with NodeCleanupFailure::InternalError,
576 "{msg} since the adaptive wait failed.");
577
578 let elapsed = fail!(from self,
579 when start.elapsed(),
580 with NodeCleanupFailure::InternalError,
581 "{msg} due to a failure while acquiring the elapsed time.");
582
583 if elapsed > timeout {
584 fail!(from self, with NodeCleanupFailure::AnotherInstanceIsCleaningUpTheNode,
585 "{msg} since another instance requires longer than {timeout:?} to cleanup the resources.");
586 }
587 }
588 }
589
590 pub fn try_remove_stale_resources(self) -> Result<(), NodeCleanupFailure> {
594 self.remove_stale_resources_impl()
595 }
596
597 fn remove_stale_resources_impl(&self) -> Result<(), NodeCleanupFailure> {
598 let msg = "Unable to remove stale resources";
599 let monitor_name = fatal_panic!(from self,
600 when FileName::new(self.id().0.value().to_string().as_bytes()),
601 "This should never happen! {msg} since the NodeId is not a valid file name.");
602
603 static IN_CLEANUP_SECTION: AtomicBool = AtomicBool::new(false);
608
609 let _cleanup_section_guard = ScopeGuardBuilder::new(&IN_CLEANUP_SECTION)
610 .on_init(|v| {
611 if v.swap(true, Ordering::Relaxed) {
613 fail!(from self, with NodeCleanupFailure::AnotherInstanceIsCleaningUpTheNode,
614 "{msg} since another instance is already cleaning up the dead nodes resources.");
615 }
616
617 Ok(())
618 })
619 .on_drop(|v| v.store(false, Ordering::Relaxed))
620 .create()?;
621
622 let config = if let Some(d) = self.details() {
623 d.config()
624 } else {
625 Config::global_config()
626 };
627
628 let cleaner = fail!(from self, when self.acquire_cleaner_lock(&monitor_name, config),
629 "{} since the monitor cleaner lock could not be acquired.", msg);
630
631 let mut cleanup_failure = Ok(());
632 let remove_node_from_service = |service_hash: &ServiceHash| {
633 match Service::__internal_remove_node_from_service(self.id(), service_hash, config) {
634 Ok(()) => (),
635 Err(ServiceRemoveNodeError::VersionMismatch) => {
636 cleanup_failure = Err(NodeCleanupFailure::VersionMismatch);
637 debug!(from self,
638 "{msg} since the dead node was using a different iceoryx2 version.");
639 }
640 Err(ServiceRemoveNodeError::Interrupt) => {
641 cleanup_failure = Err(NodeCleanupFailure::Interrupt);
642 debug!(from self,
643 "{msg} since an interrupt signal was raised while removing the node from the service.");
644 }
645 Err(ServiceRemoveNodeError::InsufficientPermissions) => {
646 cleanup_failure = Err(NodeCleanupFailure::InsufficientPermissions);
647 debug!(from self,
648 "{msg} since an interrupt signal was raised while removing the node from the service.");
649 }
650 Err(ServiceRemoveNodeError::InternalError) => {
651 cleanup_failure = Err(NodeCleanupFailure::InternalError);
652 debug!(from self,
653 "{msg} since an internal failure occurred while removing the node from the service.");
654 }
655 }
656 CallbackProgression::Continue
657 };
658
659 match Node::<Service>::service_tags(config, self.id(), remove_node_from_service) {
661 Ok(()) => (),
662 Err(NodeReadServiceTagsFailure::InsufficientPermissions) => {
663 cleaner.abandon();
664 fail!(from self, with NodeCleanupFailure::InsufficientPermissions,
665 "{} since the service tags could not be read due to insufficient permissions.", msg);
666 }
667 Err(NodeReadServiceTagsFailure::InternalError) => {
668 cleaner.abandon();
669 fail!(from self, with NodeCleanupFailure::InternalError,
670 "{} since the service tags could not be read due to an internal error.", msg);
671 }
672 };
673
674 cleanup_failure?;
675
676 match Node::<Service>::port_tags(config, self.id(), |port_id| {
679 match unsafe { remove_stale_port_resources::<Service>(self.id(), port_id, config) } {
680 Ok(()) => CallbackProgression::Continue,
681 Err(RemoveStalePortResourcesError::InsufficientPermissions) => {
682 cleanup_failure = Err(NodeCleanupFailure::InsufficientPermissions);
683 debug!(from self,
684 "{} since the stale resources of the port {port_id} could not be removed due to insufficient permissions.", msg);
685 CallbackProgression::Stop
686 }
687 Err(RemoveStalePortResourcesError::VersionMismatch) => {
688 cleanup_failure = Err(NodeCleanupFailure::VersionMismatch);
689 debug!(from self,
690 "{} since the stale resources of the port {port_id} could not be removed since the iceoryx2 version does not match.", msg);
691 CallbackProgression::Stop
692 }
693 Err(RemoveStalePortResourcesError::InternalError) => {
694 cleanup_failure = Err(NodeCleanupFailure::InternalError);
695 debug!(from self,
696 "{} since the stale resources of the port {port_id} could not be removed due to an internal failure.", msg);
697 CallbackProgression::Stop
698 }
699 Err(RemoveStalePortResourcesError::Interrupt) => {
700 cleanup_failure = Err(NodeCleanupFailure::Interrupt);
701 debug!(from self,
702 "{} since the stale resources of the port {port_id} could not be removed due to an interrupt signal.", msg);
703 CallbackProgression::Stop
704 }
705 }
706 }) {
707 Ok(()) => (),
708 Err(NodeReadPortTagsFailure::InsufficientPermissions) => {
709 cleaner.abandon();
710 fail!(from self, with NodeCleanupFailure::InsufficientPermissions,
711 "{} since the port tags could not be read due to insufficient permissions.", msg);
712 }
713 Err(NodeReadPortTagsFailure::InternalError) => {
714 cleaner.abandon();
715 fail!(from self, with NodeCleanupFailure::InternalError,
716 "{} since the port tags could not be read due to an internal error.", msg);
717 }
718 }
719
720 cleanup_failure?;
721
722 match remove_node::<Service>(*self.id(), config) {
723 Ok(_) => {
724 drop(cleaner);
725 Ok(())
726 }
727 Err(e) => {
728 cleaner.abandon();
729 fail!(from self, with e, "{} since the node itself could not be removed.", msg);
730 }
731 }
732 }
733
734 fn acquire_cleaner_lock(
735 &self,
736 monitor_name: &FileName,
737 config: &Config,
738 ) -> Result<<Service::Monitoring as Monitoring>::Cleaner, NodeCleanupFailure> {
739 let msg = "Unable to acquire monitor cleaner";
740
741 match <Service::Monitoring as Monitoring>::Builder::new(monitor_name)
742 .config(&node_monitoring_config::<Service>(config))
743 .cleaner()
744 {
745 Ok(cleaner) => Ok(cleaner),
746 Err(MonitoringCreateCleanerError::AlreadyOwnedByAnotherInstance)
747 | Err(
748 MonitoringCreateCleanerError::IsBeingCleanedUpOrAnotherCleanerCrashedDuringCleanup,
749 ) => {
750 fail!(from self, with NodeCleanupFailure::AnotherInstanceIsCleaningUpTheNode,
751 "{} since another instance is already cleaning up all resources.", msg);
752 }
753 Err(MonitoringCreateCleanerError::DoesNotExist) => {
754 fail!(from self, with NodeCleanupFailure::ResourcesAlreadyCleanedUp,
755 "{} since another instance has already cleaned up all resources.", msg);
756 }
757 Err(MonitoringCreateCleanerError::Interrupt) => {
758 fail!(from self, with NodeCleanupFailure::Interrupt,
759 "{} since an interrupt signal was received.", msg);
760 }
761 Err(MonitoringCreateCleanerError::InternalError) => {
762 fail!(from self, with NodeCleanupFailure::InternalError,
763 "{} due to an internal error while acquiring monitoring cleaner.", msg);
764 }
765 Err(MonitoringCreateCleanerError::InstanceStillAlive) => {
766 fatal_panic!(from self,
767 "This should never happen! {} since the Node is still alive.", msg);
768 }
769 }
770 }
771}
772
773fn acquire_all_node_detail_storages<Service: service::Service>(
774 origin: &str,
775 config: &<Service::StaticStorage as NamedConceptMgmt>::Configuration,
776) -> Result<Vec<FileName>, NodeCleanupFailure> {
777 let msg = "Unable to list all node detail storages";
778 match <Service::StaticStorage as NamedConceptMgmt>::list_cfg(config) {
779 Ok(v) => Ok(v),
780 Err(NamedConceptListError::InsufficientPermissions) => {
781 fail!(from origin, with NodeCleanupFailure::InsufficientPermissions,
782 "{} due to insufficient permissions.", msg);
783 }
784 Err(NamedConceptListError::InternalError) => {
785 fail!(from origin, with NodeCleanupFailure::InternalError,
786 "{} due to an internal error.", msg);
787 }
788 }
789}
790
791fn remove_detail_storages<Service: service::Service>(
792 origin: &str,
793 storages: Vec<FileName>,
794 config: &<Service::StaticStorage as NamedConceptMgmt>::Configuration,
795) -> Result<(), NodeCleanupFailure> {
796 let msg = "Unable to remove node detail storage";
797 for entry in storages {
798 match unsafe { <Service::StaticStorage as NamedConceptMgmt>::remove_cfg(&entry, config) } {
799 Ok(_) => (),
800 Err(NamedConceptRemoveError::InsufficientPermissions) => {
801 fail!(from origin, with NodeCleanupFailure::InsufficientPermissions,
802 "{} {} due to insufficient permissions.", msg, entry);
803 }
804 Err(NamedConceptRemoveError::InternalError) => {
805 fail!(from origin, with NodeCleanupFailure::InternalError,
806 "{} {} due to an internal failure.", msg, entry);
807 }
808 Err(NamedConceptRemoveError::Interrupt) => {
809 fail!(from origin, with NodeCleanupFailure::Interrupt,
810 "{} {} since an interrupt signal was raised.", msg, entry);
811 }
812 }
813 }
814
815 Ok(())
816}
817
818fn remove_node_details_directory<Service: service::Service>(
819 config: &Config,
820 node_id: &UniqueNodeId,
821) -> Result<(), NodeCleanupFailure> {
822 let origin = format!("remove_node_details_directory({config:?}, {node_id:?})");
823 let msg = "Unable to remove node details directory";
824 let path = node_details_path(config, node_id);
825 match <Service::StaticStorage as NamedConceptMgmt>::remove_path_hint(&path) {
826 Ok(()) => Ok(()),
827 Err(NamedConceptPathHintRemoveError::InsufficientPermissions) => {
828 fail!(from origin, with NodeCleanupFailure::InsufficientPermissions,
829 "{} due to insufficient permissions.", msg);
830 }
831 Err(NamedConceptPathHintRemoveError::InternalError) => {
832 fail!(from origin, with NodeCleanupFailure::InternalError,
833 "{} due to an internal error.", msg);
834 }
835 }
836}
837
838fn remove_node<Service: service::Service>(
839 id: UniqueNodeId,
840 config: &Config,
841) -> Result<bool, NodeCleanupFailure> {
842 let origin = format!(
843 "remove_node<{}>({:?})",
844 core::any::type_name::<Service>(),
845 id
846 );
847
848 let details_config = node_details_config::<Service>(config, &id);
849 let detail_storages = acquire_all_node_detail_storages::<Service>(&origin, &details_config)?;
850 remove_detail_storages::<Service>(&origin, detail_storages, &details_config)?;
851 remove_node_details_directory::<Service>(config, &id)?;
852
853 Ok(true)
854}
855
856#[derive(Debug)]
857pub(crate) struct RegisteredServices<BagHandle: BagHandleFamily> {
858 handle: MutexHandle<BTreeMap<ServiceHash, (BagHandle, u64)>>,
859}
860
861impl<BagHandle: BagHandleFamily> RegisteredServices<BagHandle> {
862 pub(crate) fn new() -> Self {
863 let origin = "RegisteredServices::new()";
864 let handle = MutexHandle::new();
865
866 fatal_panic!(
867 from origin,
868 when MutexBuilder::new()
869 .is_interprocess_capable(false)
870 .mutex_type(MutexType::Normal)
871 .create(BTreeMap::new(), &handle),
872 "Failed to create mutex"
873 );
874
875 Self { handle }
876 }
877
878 fn insert(
879 services: &mut BTreeMap<ServiceHash, (BagHandle, u64)>,
880 service_hash: ServiceHash,
881 handle: BagHandle,
882 ) {
883 if services.insert(service_hash, (handle, 1)).is_some() {
884 fatal_panic!(from "RegisteredServices::insert()",
885 "This should never happen! The service with the {:?} was already registered.",
886 service_hash);
887 }
888 }
889
890 pub(crate) fn add(&self, service_hash: &ServiceHash, handle: BagHandle) {
891 let mut guard = fatal_panic!(
892 from self,
893 when self.mutex().lock(),
894 "Failed to lock mutex"
895 );
896
897 Self::insert(&mut guard, *service_hash, handle);
898 }
899
900 pub(crate) fn add_or<F: FnMut() -> Result<BagHandle, OpenDynamicStorageFailure>>(
901 &self,
902 service_hash: &ServiceHash,
903 mut or_callback: F,
904 ) -> Result<(), OpenDynamicStorageFailure> {
905 let mut guard = fatal_panic!(
906 from self,
907 when self.mutex().lock(),
908 "Failed to lock mutex"
909 );
910
911 match guard.get_mut(service_hash) {
912 Some(entry) => {
913 entry.1 += 1;
914 }
915 None => {
916 let new_handle = or_callback()?;
917 Self::insert(&mut guard, *service_hash, new_handle);
918 }
919 };
920 Ok(())
921 }
922
923 pub(crate) fn remove<F: FnMut(BagHandle)>(
924 &self,
925 service_hash: &ServiceHash,
926 mut cleanup_call: F,
927 ) {
928 let mut guard = self.mutex().lock().expect("Failed to lock mutex");
929
930 if let Some(entry) = guard.get_mut(service_hash) {
931 entry.1 -= 1;
932 if entry.1 == 0 {
933 let handle = entry.0;
934 guard.remove(service_hash);
935 cleanup_call(handle);
936 }
937 } else {
938 fatal_panic!(from "RegisteredServices::remove()",
939 "This should never happen! The service with the {:?} was not registered.", service_hash);
940 }
941
942 drop(guard);
943 }
944
945 fn mutex(&self) -> Mutex<'_, '_, BTreeMap<ServiceHash, (BagHandle, u64)>> {
946 unsafe { Mutex::from_handle(&self.handle) }
949 }
950}
951
952#[derive(Debug)]
953struct SharedNodeState<Service: service::Service> {
954 id: UniqueNodeId,
955 details: NodeDetails,
956 monitoring_token: UnsafeCell<Option<<Service::Monitoring as Monitoring>::Token>>,
957 registered_services: RegisteredServices<<Service::Bag as BagFamily>::BagHandle>,
958 signal_handling_mode: SignalHandlingMode,
959 details_storage: Service::StaticStorage,
960}
961
962unsafe impl<Service: service::Service> Send for SharedNodeState<Service> {}
963unsafe impl<Service: service::Service> Sync for SharedNodeState<Service> {}
964
965impl<Service: service::Service> Abandonable for SharedNodeState<Service> {
966 unsafe fn abandon_in_place(mut this: NonNull<Self>) {
967 let this = unsafe { this.as_mut() };
968 unsafe {
969 <Service::StaticStorage as Abandonable>::abandon_in_place(NonNull::from_mut(
970 &mut this.details_storage,
971 ))
972 };
973 if let Some(token) = this.monitoring_token.get_mut() {
974 unsafe {
975 <<Service::Monitoring as Monitoring>::Token as Abandonable>::abandon_in_place(
976 NonNull::from_mut(token),
977 )
978 };
979 }
980 }
981}
982
983impl<Service: service::Service> SharedNodeState<Service> {
984 pub(crate) fn blocking_cleanup_dead_nodes(&self, timeout: Duration) -> CleanupState {
985 let mut cleanup_state = CleanupState {
986 cleanups: 0,
987 failed_cleanups: 0,
988 };
989 let origin = format!(
990 "Node::<{}>::cleanup_dead_nodes()",
991 core::any::type_name::<Service>()
992 );
993
994 let cleanup_call = |node_state| {
995 if let NodeState::Dead(dead_node) = node_state {
996 let node_id = *dead_node.id();
997 debug!(from origin, "Dead node ({:?}) detected", node_id);
998 match dead_node.blocking_remove_stale_resources(timeout) {
999 Ok(_) => {
1000 cleanup_state.cleanups += 1;
1001 trace!(from origin, "The dead node ({:?}) was successfully removed.", node_id)
1002 }
1003 Err(e) => {
1004 cleanup_state.failed_cleanups += 1;
1005 trace!(from origin, "Unable to remove dead node {:?} ({:?}).", node_id, e)
1006 }
1007 }
1008 }
1009
1010 CallbackProgression::Continue
1011 };
1012
1013 match Node::<Service>::list(&self.details.config, cleanup_call) {
1014 Ok(()) => cleanup_state,
1015 Err(e) => {
1016 debug!(from origin, "Unable to perform a full scan for dead nodes since the all existing nodes could not be listed ({:?}).", e);
1017 cleanup_state
1018 }
1019 }
1020 }
1021}
1022
1023impl<Service: service::Service> Drop for SharedNodeState<Service> {
1024 fn drop(&mut self) {
1025 let config = self.details.config();
1026 if self.monitoring_token.get_mut().is_some() {
1027 if config.global.node.cleanup_dead_nodes_on_destruction {
1028 self.blocking_cleanup_dead_nodes(Duration::ZERO);
1029 }
1030
1031 warn!(from self, when remove_node::<Service>(self.id, config),
1032 "Unable to remove node resources.");
1033 }
1034
1035 trace!(from self, "removed");
1036 }
1037}
1038
1039#[derive(Debug, Clone)]
1040pub(crate) struct SharedNode<Service: service::Service> {
1041 state: Arc<SharedNodeState<Service>>,
1042}
1043
1044impl<Service: service::Service> Abandonable for SharedNode<Service> {
1045 unsafe fn abandon_in_place(mut this: NonNull<Self>) {
1046 let this = unsafe { this.as_mut() };
1047 if let Some(state) = Arc::get_mut(&mut this.state) {
1048 unsafe { SharedNodeState::abandon_in_place(NonNull::from_mut(state)) };
1049 } else {
1050 unsafe { core::ptr::drop_in_place(&mut this.state) };
1051 }
1052 }
1053}
1054
1055impl<Service: service::Service> SharedNode<Service> {
1056 pub(crate) fn config(&self) -> &Config {
1057 &self.state.details.config
1058 }
1059
1060 pub(crate) fn id(&self) -> &UniqueNodeId {
1061 &self.state.id
1062 }
1063
1064 pub(crate) fn registered_services(
1065 &self,
1066 ) -> &RegisteredServices<<Service::Bag as BagFamily>::BagHandle> {
1067 &self.state.registered_services
1068 }
1069
1070 pub(crate) fn name(&self) -> &NodeName {
1071 &self.state.details.name
1072 }
1073
1074 pub(crate) fn create_port_tag(
1075 &self,
1076 origin: &str,
1077 msg: &str,
1078 port_id: u128,
1079 ) -> Result<Service::StaticStorage, StaticStorageCreateError> {
1080 let name = FileName::new(port_id.to_string().as_bytes())
1081 .expect("A number is always a valid file name.");
1082
1083 match <<Service::StaticStorage as StaticStorage>::Builder as NamedConceptBuilder<
1084 Service::StaticStorage,
1085 >>::new(&name)
1086 .config(&port_tag_config::<Service>(self.config(), self.id()))
1087 .has_ownership(true)
1088 .create(&[])
1089 {
1090 Ok(static_storage) => Ok(static_storage),
1091 Err(e) => {
1092 fail!(from origin, with e,
1093 "{msg} since the port tag could not be created. [{e:?}]");
1094 }
1095 }
1096 }
1097
1098 pub(crate) fn create_service_tag<T: Debug + ?Sized>(
1099 &self,
1100 origin: &T,
1101 msg: &str,
1102 service_hash: &ServiceHash,
1103 ) -> Result<Option<Service::StaticStorage>, StaticStorageCreateError> {
1104 match <<Service::StaticStorage as StaticStorage>::Builder as NamedConceptBuilder<
1105 Service::StaticStorage,
1106 >>::new(&service_hash.0.into())
1107 .config(&service_tag_config::<Service>(self.config(), self.id()))
1108 .has_ownership(true)
1109 .create(&[])
1110 {
1111 Ok(static_storage) => Ok(Some(static_storage)),
1112 Err(StaticStorageCreateError::AlreadyExists) => Ok(None),
1113 Err(e) => {
1114 fail!(from origin, with e,
1115 "{msg} since the service tag could not be created. [{e:?}]");
1116 }
1117 }
1118 }
1119}
1120
1121#[derive(Debug)]
1129pub struct Node<Service: service::Service> {
1130 pub(crate) shared: SharedNode<Service>,
1131}
1132
1133unsafe impl<Service: service::Service> Send for Node<Service> {}
1134
1135impl<Service: service::Service> Abandonable for Node<Service> {
1136 unsafe fn abandon_in_place(mut this: NonNull<Self>) {
1137 let this = unsafe { this.as_mut() };
1138 unsafe { SharedNode::abandon_in_place(NonNull::from_mut(&mut this.shared)) };
1139 }
1140}
1141
1142impl<Service: service::Service> Node<Service> {
1143 pub fn name(&self) -> &NodeName {
1145 self.shared.name()
1146 }
1147
1148 pub fn config(&self) -> &Config {
1150 self.shared.config()
1151 }
1152
1153 pub fn id(&self) -> &UniqueNodeId {
1155 self.shared.id()
1156 }
1157
1158 pub fn service_builder(&self, name: &ServiceName) -> Builder<Service> {
1160 Builder::new(name, self.shared.clone())
1161 }
1162
1163 pub fn state_of(
1166 config: &Config,
1167 node_id: UniqueNodeId,
1168 ) -> Result<Option<NodeState<Service>>, NodeListFailure> {
1169 let mut node_state = None;
1170 match Node::list(config, |v| {
1171 if *v.node_id() == node_id {
1172 node_state = Some(v);
1173 CallbackProgression::Stop
1174 } else {
1175 CallbackProgression::Continue
1176 }
1177 }) {
1178 Ok(()) => Ok(node_state),
1179 Err(e) => {
1180 fail!(from "Node::state_of()", with e,
1181 "Unable to acquire the node state of \"{node_id}\" due to a failure while listing all nodes. [{e:?}]");
1182 }
1183 }
1184 }
1185
1186 pub fn list<F: FnMut(NodeState<Service>) -> CallbackProgression>(
1198 config: &Config,
1199 mut callback: F,
1200 ) -> Result<(), NodeListFailure> {
1201 let msg = "Unable to iterate over Node list";
1202 let origin = "Node::list()";
1203 let monitoring_config = node_monitoring_config::<Service>(config);
1204
1205 match Self::list_all_nodes(&monitoring_config) {
1206 Ok(node_list) => {
1207 for node_name in node_list {
1208 let Ok(node_id) = core::str::from_utf8(node_name.as_bytes()) else {
1210 continue;
1211 };
1212 let node_id = match node_id.parse::<u128>() {
1213 Ok(v) => UniqueNodeId(unsafe { UniqueId::from_raw_id(v) }),
1214 Err(_) => continue,
1215 };
1216
1217 match NodeState::new(&node_id, config) {
1218 Ok(Some(node_state)) => {
1219 if callback(node_state) == CallbackProgression::Stop {
1220 break;
1221 }
1222 }
1223 Ok(None) => (),
1224 Err(e) => {
1225 fail!(from origin, with e,
1226 "{msg} since the following error occurred ({:?}).", e);
1227 }
1228 }
1229 }
1230 }
1231 Err(e) => {
1232 fail!(from origin, with e,
1233 "{msg} since the node list could not be acquired ({:?}).", e);
1234 }
1235 }
1236
1237 Ok(())
1238 }
1239
1240 fn handle_termination_request(&self, error_msg: &str) -> Result<(), NodeWaitFailure> {
1241 if self.signal_handling_mode() == SignalHandlingMode::HandleTerminationRequests
1242 && SignalHandler::termination_requested()
1243 {
1244 fail!(from self, with NodeWaitFailure::TerminationRequest,
1245 "{error_msg} since a termination request was received.");
1246 }
1247
1248 Ok(())
1249 }
1250
1251 pub fn wait(&self, cycle_time: Duration) -> Result<(), NodeWaitFailure> {
1255 let msg = "Unable to wait on node";
1256 self.handle_termination_request(msg)?;
1257
1258 match nanosleep(cycle_time) {
1259 Ok(()) => {
1260 self.handle_termination_request(msg)?;
1261 Ok(())
1262 }
1263 Err(NanosleepError::InterruptedBySignal(_)) => {
1264 fail!(from self, with NodeWaitFailure::Interrupt,
1265 "{msg} since a interrupt signal was received.");
1266 }
1267 Err(v) => {
1268 fatal_panic!(from self,
1269 "Failed to wait with cycle time {:?} in main event look, caused by ({:?}).",
1270 cycle_time, v);
1271 }
1272 }
1273 }
1274
1275 pub fn signal_handling_mode(&self) -> SignalHandlingMode {
1277 self.shared.state.signal_handling_mode
1278 }
1279
1280 pub fn try_cleanup_dead_nodes(&self) -> CleanupState {
1286 self.shared
1287 .state
1288 .blocking_cleanup_dead_nodes(Duration::ZERO)
1289 }
1290
1291 pub fn blocking_cleanup_dead_nodes(&self, timeout: Duration) -> CleanupState {
1300 self.shared.state.blocking_cleanup_dead_nodes(timeout)
1301 }
1302
1303 pub unsafe fn force_remove_service(
1312 &self,
1313 name: &ServiceName,
1314 messaging_pattern: MessagingPattern,
1315 ) -> Result<bool, ServiceRemoveError> {
1316 unsafe { Service::__internal_force_remove_service(name, self.config(), messaging_pattern) }
1317 }
1318
1319 fn list_all_nodes(
1320 config: &<Service::Monitoring as NamedConceptMgmt>::Configuration,
1321 ) -> Result<Vec<FileName>, NodeListFailure> {
1322 let result = <Service::Monitoring as NamedConceptMgmt>::list_cfg(config);
1323
1324 if let Ok(result) = result {
1325 return Ok(result);
1326 }
1327
1328 let msg = "Unable to list all nodes";
1329 let origin = format!("Node::list_all_nodes({config:?})");
1330 match result.err().unwrap() {
1331 NamedConceptListError::InsufficientPermissions => {
1332 fail!(from origin, with NodeListFailure::InsufficientPermissions,
1333 "{} due to insufficient permissions while listing all nodes.", msg);
1334 }
1335 NamedConceptListError::InternalError => {
1336 fail!(from origin, with NodeListFailure::InternalError,
1337 "{} due to an internal failure while listing all nodes.", msg);
1338 }
1339 }
1340 }
1341
1342 fn state_from_monitor(
1343 monitor: &<Service::Monitoring as Monitoring>::Monitor,
1344 ) -> Result<State, NodeListFailure> {
1345 let result = monitor.state();
1346
1347 if let Ok(result) = result {
1348 return Ok(result);
1349 }
1350
1351 let msg = "Unable to acquire node state from monitor";
1352 let origin = format!("Node::state_from_monitor({monitor:?})");
1353
1354 match result.err().unwrap() {
1355 MonitoringStateError::InsufficientPermissions => {
1356 fail!(from origin, with NodeListFailure::InsufficientPermissions,
1357 "{} due to insufficient permissions to acquire the nodes state.", msg);
1358 }
1359 MonitoringStateError::Interrupt => {
1360 fail!(from origin, with NodeListFailure::Interrupt,
1361 "{} due to an interrupt signal while acquiring the nodes state.", msg);
1362 }
1363 MonitoringStateError::InternalError => {
1364 fail!(from origin, with NodeListFailure::InternalError,
1365 "{} due to an internal error while acquiring the nodes state.", msg);
1366 }
1367 }
1368 }
1369
1370 fn get_node_state(config: &Config, node_id: &UniqueNodeId) -> Result<State, NodeListFailure> {
1371 let config = node_monitoring_config::<Service>(config);
1372 let result = <Service::Monitoring as Monitoring>::Builder::new(&node_id.as_file_name())
1373 .config(&config)
1374 .monitor();
1375
1376 if let Ok(result) = result {
1377 return Self::state_from_monitor(&result);
1378 }
1379
1380 let msg = "Unable to acquire node monitor";
1381 let origin = format!("Node::get_node_state({config:?}, {node_id:?})");
1382 match result.err().unwrap() {
1383 MonitoringCreateMonitorError::InsufficientPermissions => {
1384 fail!(from origin, with NodeListFailure::InsufficientPermissions,
1385 "{} due to insufficient permissions while acquiring the node state.", msg);
1386 }
1387 MonitoringCreateMonitorError::Interrupt => {
1388 fail!(from origin, with NodeListFailure::Interrupt,
1389 "{} since an interrupt was received while acquiring the node state.", msg);
1390 }
1391 MonitoringCreateMonitorError::InternalError
1392 | MonitoringCreateMonitorError::ConceptNameNotSupportedOnPlatform => {
1393 fail!(from origin, with NodeListFailure::InternalError,
1394 "{} since an internal failure occurred while acquiring the node state.", msg);
1395 }
1396 }
1397 }
1398
1399 fn open_node_storage(
1400 config: &Config,
1401 node_id: &UniqueNodeId,
1402 ) -> Result<Option<Service::StaticStorage>, NodeReadStorageFailure> {
1403 let details_config = node_details_config::<Service>(config, node_id);
1404 let msg = "Unable to open node config storage";
1405 let origin = format!("open_node_storage({config:?}, {node_id:?})");
1406
1407 match <Service::StaticStorage as StaticStorage>::Builder::new(
1408 &FileName::new(b"node").unwrap(),
1409 )
1410 .config(&details_config)
1411 .has_ownership(false)
1412 .open(Duration::ZERO)
1413 {
1414 Ok(result) => Ok(Some(result)),
1415 Err(StaticStorageOpenError::DoesNotExist) => Ok(None),
1416 Err(StaticStorageOpenError::Read) => {
1417 fail!(from origin, with NodeReadStorageFailure::ReadError,
1418 "{} since the node config storage could not be read.", msg);
1419 }
1420 Err(StaticStorageOpenError::InitializationNotYetFinalized) => {
1421 fail!(from origin, with NodeReadStorageFailure::Corrupted,
1422 "{} since the node config storage seems to be uninitialized but the state should always be present.", msg);
1423 }
1424 Err(StaticStorageOpenError::InternalError) => {
1425 fail!(from origin, with NodeReadStorageFailure::InternalError,
1426 "{} due to an internal failure while opening the node config storage.", msg);
1427 }
1428 Err(StaticStorageOpenError::Interrupt) => {
1429 fail!(from origin, with NodeReadStorageFailure::Interrupt,
1430 "{} since an interrupt signal was raised.", msg);
1431 }
1432 Err(StaticStorageOpenError::InsufficientPermissions) => {
1433 fail!(from origin, with NodeReadStorageFailure::InsufficientPermissions,
1434 "{} due to insufficient permissions.", msg);
1435 }
1436 }
1437 }
1438
1439 fn get_node_details(
1440 config: &Config,
1441 node_id: &UniqueNodeId,
1442 ) -> Result<Option<NodeDetails>, NodeReadStorageFailure> {
1443 let node_storage = if let Some(n) = Self::open_node_storage(config, node_id)? {
1444 n
1445 } else {
1446 return Ok(None);
1447 };
1448
1449 let mut read_content =
1450 String::from_utf8(vec![b' '; node_storage.len() as usize]).expect("");
1451
1452 let origin = format!("get_node_details({config:?}, {node_id:?})");
1453 let msg = "Unable to read node details";
1454
1455 if node_storage
1456 .read(unsafe { read_content.as_mut_vec() }.as_mut_slice())
1457 .is_err()
1458 {
1459 fail!(from origin, with NodeReadStorageFailure::ReadError,
1460 "{} since the content of the node config storage could not be read.", msg);
1461 }
1462
1463 let node_details = fail!(from origin,
1464 when Service::ConfigSerializer::deserialize::<NodeDetails>(unsafe { read_content.as_mut_vec()}),
1465 with NodeReadStorageFailure::Corrupted,
1466 "{} since the contents of the node config storage is corrupted.", msg);
1467
1468 Ok(Some(node_details))
1469 }
1470
1471 fn port_tags<F: FnMut(u128) -> CallbackProgression>(
1472 config: &Config,
1473 node_id: &UniqueNodeId,
1474 mut callback: F,
1475 ) -> Result<(), NodeReadPortTagsFailure> {
1476 let origin = "Node::service_tags()";
1477 let msg = format!("Unable to acquire all port tags of the node {node_id:?}");
1478 match <Service::StaticStorage as NamedConceptMgmt>::list_cfg(&port_tag_config::<Service>(
1479 config, node_id,
1480 )) {
1481 Ok(tags) => {
1482 for tag in &tags {
1483 if let Ok(v) = tag.to_string().parse::<u128>() {
1484 if callback(v) == CallbackProgression::Stop {
1485 break;
1486 }
1487 } else {
1488 continue;
1489 }
1490 }
1491 Ok(())
1492 }
1493 Err(NamedConceptListError::InsufficientPermissions) => {
1494 fail!(from origin, with NodeReadPortTagsFailure::InsufficientPermissions,
1495 "{} due to insufficient permissions.", msg);
1496 }
1497 Err(NamedConceptListError::InternalError) => {
1498 fail!(from origin, with NodeReadPortTagsFailure::InternalError,
1499 "{} due to an internal error.", msg);
1500 }
1501 }
1502 }
1503
1504 fn service_tags<F: FnMut(&ServiceHash) -> CallbackProgression>(
1505 config: &Config,
1506 node_id: &UniqueNodeId,
1507 mut callback: F,
1508 ) -> Result<(), NodeReadServiceTagsFailure> {
1509 let origin = "Node::service_tags()";
1510 let msg = format!("Unable to acquire all service tags of the node {node_id:?}");
1511 match <Service::StaticStorage as NamedConceptMgmt>::list_cfg(
1512 &service_tag_config::<Service>(config, node_id),
1513 ) {
1514 Ok(tags) => {
1515 for tag in &tags {
1516 if let Ok(v) = tag.try_into() {
1517 if callback(&ServiceHash(v)) == CallbackProgression::Stop {
1518 break;
1519 }
1520 } else {
1521 continue;
1522 }
1523 }
1524 Ok(())
1525 }
1526 Err(NamedConceptListError::InsufficientPermissions) => {
1527 fail!(from origin, with NodeReadServiceTagsFailure::InsufficientPermissions,
1528 "{} due to insufficient permissions.", msg);
1529 }
1530 Err(NamedConceptListError::InternalError) => {
1531 fail!(from origin, with NodeReadServiceTagsFailure::InternalError,
1532 "{} due to an internal error.", msg);
1533 }
1534 }
1535 }
1536}
1537
1538#[derive(Debug, Default, Clone)]
1553pub struct NodeBuilder {
1554 name: Option<NodeName>,
1555 signal_handling_mode: SignalHandlingMode,
1556 config: Option<Config>,
1557}
1558
1559impl NodeBuilder {
1560 pub fn new() -> Self {
1562 Self::default()
1563 }
1564
1565 pub fn name(mut self, value: &NodeName) -> Self {
1567 self.name = Some(value.clone());
1568 self
1569 }
1570
1571 pub fn signal_handling_mode(mut self, value: SignalHandlingMode) -> Self {
1575 self.signal_handling_mode = value;
1576 self
1577 }
1578
1579 pub fn config(mut self, value: &Config) -> Self {
1582 self.config = Some(value.clone());
1583 self
1584 }
1585
1586 pub fn create<Service: service::Service>(self) -> Result<Node<Service>, NodeCreationFailure> {
1589 let msg = "Unable to create node";
1590
1591 let config = self
1592 .config
1593 .as_ref()
1594 .unwrap_or_else(|| Config::global_config());
1595
1596 let name = match &self.name {
1597 Some(n) => n.clone(),
1598 None => NodeName::default(),
1599 };
1600 let node_id = fail!(from self, when UniqueNodeId::new::<Service>(name, config),
1601 with NodeCreationFailure::UnableToGenerateUniqueNodeId,
1602 "{msg} since the UniqueNodeId could not be generated.");
1603
1604 let monitor_name = fatal_panic!(from self, when FileName::new(node_id.value().to_string().as_bytes()),
1605 "This should never happen! {msg} since the UniqueNodeId is not a valid file name.");
1606 let (details_storage, details) =
1607 self.create_node_details_storage::<Service>(config, &node_id)?;
1608 let monitoring_token = self.create_token::<Service>(config, &monitor_name)?;
1609
1610 let state = Arc::new(SharedNodeState {
1611 id: node_id,
1612 monitoring_token: UnsafeCell::new(Some(monitoring_token)),
1613 registered_services: RegisteredServices::new(),
1614 details_storage,
1615 signal_handling_mode: self.signal_handling_mode,
1616 details,
1617 });
1618
1619 if config.global.node.cleanup_dead_nodes_on_creation {
1620 state.blocking_cleanup_dead_nodes(Duration::ZERO);
1621 }
1622
1623 let new_node = Node {
1624 shared: SharedNode { state },
1625 };
1626
1627 trace!(from new_node, "created");
1628 Ok(new_node)
1629 }
1630
1631 fn create_token<Service: service::Service>(
1632 &self,
1633 config: &Config,
1634 monitor_name: &FileName,
1635 ) -> Result<<Service::Monitoring as Monitoring>::Token, NodeCreationFailure> {
1636 let msg = "Unable to create token for new node";
1637 let token_result = <Service::Monitoring as Monitoring>::Builder::new(monitor_name)
1638 .config(&node_monitoring_config::<Service>(config))
1639 .token();
1640
1641 match token_result {
1642 Ok(token) => Ok(token),
1643 Err(MonitoringCreateTokenError::InsufficientPermissions) => {
1644 fail!(from self, with NodeCreationFailure::InsufficientPermissions,
1645 "{msg} due to insufficient permissions to create a monitor token.");
1646 }
1647 Err(MonitoringCreateTokenError::AlreadyExists) => {
1648 fatal_panic!(from self,
1649 "This should never happen! {msg} since a node with the same UniqueNodeId already exists.");
1650 }
1651 Err(MonitoringCreateTokenError::InternalError) => {
1652 fail!(from self, with NodeCreationFailure::InternalError,
1653 "{msg} since the monitor token could not be created.");
1654 }
1655 Err(MonitoringCreateTokenError::SystemCorrupted) => {
1656 fail!(from self, with NodeCreationFailure::SystemCorrupted,
1657 "{msg} since some external instance removed the underlying resources of the monitoring token.");
1658 }
1659 }
1660 }
1661
1662 fn create_node_details_storage<Service: service::Service>(
1663 &self,
1664 config: &Config,
1665 node_id: &UniqueNodeId,
1666 ) -> Result<(Service::StaticStorage, NodeDetails), NodeCreationFailure> {
1667 let msg = "Unable to create node details storage";
1668 let details = NodeDetails::new(&self.name, config);
1669
1670 let details_config = node_details_config::<Service>(&details.config, node_id);
1671 let serialized_details = match <Service::ConfigSerializer>::serialize(&details) {
1672 Ok(serialized_details) => serialized_details,
1673 Err(SerializeError::InternalError) => {
1674 fail!(from self, with NodeCreationFailure::InternalError,
1675 "{msg} since the node details could not be serialized.");
1676 }
1677 };
1678
1679 match <Service::StaticStorage as StaticStorage>::Builder::new(
1680 &FileName::new(b"node").unwrap(),
1681 )
1682 .config(&details_config)
1683 .has_ownership(false)
1684 .create(&serialized_details)
1685 {
1686 Ok(node_details) => Ok((node_details, details)),
1687 Err(StaticStorageCreateError::InsufficientPermissions) => {
1688 fail!(from self, with NodeCreationFailure::InsufficientPermissions,
1689 "{msg} due to insufficient permissions to create the node details file.");
1690 }
1691 Err(StaticStorageCreateError::AlreadyExists) => {
1692 fatal_panic!(from self,
1693 "This should never happen! {msg} since the node details file already exists.");
1694 }
1695 Err(e) => {
1696 fail!(from self, with NodeCreationFailure::InternalError,
1697 "{msg} due to an unknown failure while creating the node details file {:?}.", e);
1698 }
1699 }
1700 }
1701}