diff --git a/examples/README.md b/examples/README.md index 26291f249..a1dbf54f2 100644 --- a/examples/README.md +++ b/examples/README.md @@ -79,7 +79,7 @@ These types are demonstrated in the complex data types example. | event | [C](c/event) [C++](cxx/event) [Rust](rust/event) | Push notifications - send event signals to wakeup processes that are waiting for them. | | event based communication | [C++](cxx/event_based_communication) [Rust](rust/event_based_communication) | Define multiple events like publisher/subscriber created or removed, send sample, received sample, deliver history etc. and react on them for a fully event driven communication setup. | | event multiplexing | [C](c/event_multiplexing) [C++](cxx/event_multiplexing) [Rust](rust/event_multiplexing) | Wait on multiple listeners or sockets with a single call. The WaitSet demultiplexes incoming events and notifies the user. | -| health monitoring | [Rust](rust/health_monitoring) | A central daemon creates the communication resources and monitors all nodes. When the central daemon crashes other nodes can take over and use the decentral API to monitor the nodes. | +| health monitoring | [C++](cxx/health_monitoring) [Rust](rust/health_monitoring) | A central daemon creates the communication resources and monitors all nodes. When the central daemon crashes other nodes can take over and use the decentral API to monitor the nodes. | | publish subscribe | [C](c/publish_subscribe) [C++](cxx/publish_subscribe) [Rust](rust/publish_subscribe) | Communication between multiple processes with a [publish subscribe messaging pattern](https://en.wikipedia.org/wiki/Publish–subscribe_pattern). | | publish subscribe dynamic data | [C++](cxx/publish_subscribe_dynamic_data) [Rust](rust/publish_subscribe_dynamic_data) | Communication between multiple processes with a [publish subscribe messaging pattern](https://en.wikipedia.org/wiki/Publish–subscribe_pattern) and payload data that has a dynamic size. | | publish subscribe with user header | [C](c/publish_subscribe_with_user_header) [C++](cxx/publish_subscribe_with_user_header) [Rust](rust/publish_subscribe_with_user_header) | Add a user header to the payload (samples) to transfer additional information. | diff --git a/examples/cxx/health_monitoring/README.md b/examples/cxx/health_monitoring/README.md index 8b1378917..66f78b039 100644 --- a/examples/cxx/health_monitoring/README.md +++ b/examples/cxx/health_monitoring/README.md @@ -1 +1,140 @@ +# Health Monitoring +Before proceeding, all dependencies need to be installed. You can find +instructions in the [C++ Examples Readme](../README.md). + +This example demonstrates how to create a robust system using iceoryx2. +A central daemon pre-creates all communication resources to ensure that every +required resource, such as memory, is available as soon as the application +starts. +Additionally, the subscriber is immediately informed if one of the processes +it depends on has crashed. Even if the central daemon itself crashes, +communication can continue without any restrictions. Thanks to the +decentralized API of iceoryx2, the subscriber can take over the role of the +central daemon and continue monitoring all processes. + +The communication must also be reliable, and we expect publishers to provide +updates at regular intervals. If a publisher misses a deadline, we want to be +informed immediately. This situation can occur if the system is under heavy +load or if a process has crashed. + +This example is more advanced and consists of four components: + +* `central_daemon` - Must run first. It creates all communication resources and + monitors all nodes/processes. +* `publisher_1` - Sends data at a specific frequency on `service_1`. +* `publisher_2` - Sends data at a specific frequency on `service_2`. +* `subscriber` - Connects to `service_1` and `service_2` and expects new samples + within a specific time. If no sample arrives, it proactively checks for dead + nodes. + +```ascii ++----------------+ creates ........................... +| central_daemon | ----------> : communication resources : ++----------------+ ........................... + | ^ + | opens | + | +-----------------+--------------+ + | | | | + | +-------------+ +-------------+ +------------+ + | | publisher_1 | | publisher_2 | | subscriber | + | +-------------+ +-------------+ +------------+ + | ^ ^ ^ + | monitores | | | + +-------------+-------------------+-----------------+ +``` + +## Running The Example + +> [!CAUTION] +> Every payload you transmit with iceoryx2 must be compatible with shared +> memory. Specifically, it must: +> +> * be self contained, no heap, no pointers to external sources +> * have a uniform memory representation -> `#[repr(C)]` +> * not use pointers to manage their internal structure +> +> Data types like `String` or `Vec` will cause undefined behavior and may +> result in segmentation faults. We provide alternative data types that are +> compatible with shared memory. See the +> [complex data type example](../complex_data_types) for guidance on how to +> use them. + +First you have to build the C++ examples: + +```sh +cmake -S . -B target/ffi/build -DBUILD_EXAMPLES=ON +cmake --build target/ffi/build +``` + +For this example, you need to open five separate terminals. + +## Terminal 1: Central Daemon - Create All Communication Resources + +Run the central daemon, which sets up all communication resources and monitors +processes. + +```sh +./target/ffi/build/examples/cxx/health_monitoring/example_cxx_health_monitoring_central_daemon +``` + +## Terminal 2: Publisher 1 + +Run the first publisher, which sends data on `service_1`. + +```sh +./target/ffi/build/examples/cxx/health_monitoring/example_cxx_health_monitoring_publisher_1 +``` + +## Terminal 3: Publisher 2 + +Run the second publisher, which sends data on `service_2`. + +```sh +./target/ffi/build/examples/cxx/health_monitoring/example_cxx_health_monitoring_publisher_2 +``` + +## Terminal 4: Subscriber + +Run the subscriber, which listens to both `service_1` and `service_2`. + +```sh +./target/ffi/build/examples/cxx/health_monitoring/example_cxx_health_monitoring_subscriber +``` + +## Terminal 5: Simulate Process Crashes + +Send a `SIGKILL` signal to `publisher_1` to simulate a fatal crash. This +ensures that the process is unable to clean up any resources. + +```sh +killall -9 example_cxx_health_monitoring_publisher_1 +``` + +After running this command: + +1. The `central_daemon` will detect that the process has crashed and print: + ```ascii + detected dead node: Some(NodeName { value: "publisher 1" }) + ``` + The event service is configured to emit a `PubSub::ProcessDied` event when a + process is identified as dead. + +2. On the `subscriber` side, you will see the message: + ```ascii + ServiceName { value: "service_1" }: process died! + ``` + +3. Since `publisher_1` is no longer sending messages, the subscriber will also + regularly print another message indicating that `service_1` has violated + the contract because no new samples are being received. + +Feel free to run multiple instances of publisher or subscriber processes +simultaneously to explore how iceoryx2 handles publisher-subscriber +communication efficiently. + +You may hit the maximum supported number of ports when too many publisher or +subscriber processes run. Take a look at the [iceoryx2 config](../../../config) +to set the limits globally or at the +[API of the Service builder](https://docs.rs/iceoryx2/latest/iceoryx2/service/index.html) +to set them for a single service. diff --git a/examples/rust/health_monitoring/README.md b/examples/rust/health_monitoring/README.md index 776958610..e2c5a6ede 100644 --- a/examples/rust/health_monitoring/README.md +++ b/examples/rust/health_monitoring/README.md @@ -118,3 +118,13 @@ After running this command: 3. Since `publisher_1` is no longer sending messages, the subscriber will also regularly print another message indicating that `service_1` has violated the contract because no new samples are being received. + +Feel free to run multiple instances of publisher or subscriber processes +simultaneously to explore how iceoryx2 handles publisher-subscriber +communication efficiently. + +You may hit the maximum supported number of ports when too many publisher or +subscriber processes run. Take a look at the [iceoryx2 config](../../../config) +to set the limits globally or at the +[API of the Service builder](https://docs.rs/iceoryx2/latest/iceoryx2/service/index.html) +to set them for a single service.