-
Notifications
You must be signed in to change notification settings - Fork 42
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[#555] Add c++ health monitoring example
- Loading branch information
Showing
10 changed files
with
508 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
# Copyright (c) 2024 Contributors to the Eclipse Foundation | ||
# | ||
# See the NOTICE file(s) distributed with this work for additional | ||
# information regarding copyright ownership. | ||
# | ||
# This program and the accompanying materials are made available under the | ||
# terms of the Apache Software License 2.0 which is available at | ||
# https://www.apache.org/licenses/LICENSE-2.0, or the MIT license | ||
# which is available at https://opensource.org/licenses/MIT. | ||
# | ||
# SPDX-License-Identifier: Apache-2.0 OR MIT | ||
|
||
load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library") | ||
|
||
cc_binary( | ||
name = "example_cxx_health_monitoring_central_daemon", | ||
srcs = [ | ||
"src/central_daemon.cpp", | ||
"src/pubsub_event.hpp" | ||
], | ||
deps = [ | ||
"@iceoryx//:iceoryx_hoofs", | ||
"//:iceoryx2-cxx-static", | ||
], | ||
) | ||
|
||
cc_binary( | ||
name = "example_cxx_health_monitoring_publisher_1", | ||
srcs = [ | ||
"src/publisher_1.cpp", | ||
"src/pubsub_event.hpp" | ||
], | ||
deps = [ | ||
"@iceoryx//:iceoryx_hoofs", | ||
"//:iceoryx2-cxx-static", | ||
], | ||
) | ||
|
||
cc_binary( | ||
name = "example_cxx_health_monitoring_publisher_2", | ||
srcs = [ | ||
"src/publisher_2.cpp", | ||
"src/pubsub_event.hpp" | ||
], | ||
deps = [ | ||
"@iceoryx//:iceoryx_hoofs", | ||
"//:iceoryx2-cxx-static", | ||
], | ||
) | ||
|
||
cc_binary( | ||
name = "example_cxx_health_monitoring_subscriber", | ||
srcs = [ | ||
"src/subscriber.cpp", | ||
"src/pubsub_event.hpp" | ||
], | ||
deps = [ | ||
"@iceoryx//:iceoryx_hoofs", | ||
"//:iceoryx2-cxx-static", | ||
], | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
# Copyright (c) 2024 Contributors to the Eclipse Foundation | ||
# | ||
# See the NOTICE file(s) distributed with this work for additional | ||
# information regarding copyright ownership. | ||
# | ||
# This program and the accompanying materials are made available under the | ||
# terms of the Apache Software License 2.0 which is available at | ||
# https://www.apache.org/licenses/LICENSE-2.0, or the MIT license | ||
# which is available at https://opensource.org/licenses/MIT. | ||
# | ||
# SPDX-License-Identifier: Apache-2.0 OR MIT | ||
|
||
cmake_minimum_required(VERSION 3.22) | ||
project(example_cxx_health_monitoring LANGUAGES CXX) | ||
|
||
find_package(iceoryx2-cxx 0.4.1 REQUIRED) | ||
|
||
add_executable(example_cxx_health_monitoring_central_daemon src/central_daemon.cpp) | ||
target_link_libraries(example_cxx_health_monitoring_central_daemon iceoryx2-cxx::static-lib-cxx) | ||
|
||
add_executable(example_cxx_health_monitoring_publisher_1 src/publisher_1.cpp) | ||
target_link_libraries(example_cxx_health_monitoring_publisher_1 iceoryx2-cxx::static-lib-cxx) | ||
|
||
add_executable(example_cxx_health_monitoring_publisher_2 src/publisher_2.cpp) | ||
target_link_libraries(example_cxx_health_monitoring_publisher_2 iceoryx2-cxx::static-lib-cxx) | ||
|
||
add_executable(example_cxx_health_monitoring_subscriber src/subscriber.cpp) | ||
target_link_libraries(example_cxx_health_monitoring_subscriber iceoryx2-cxx::static-lib-cxx) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
// Copyright (c) 2024 Contributors to the Eclipse Foundation | ||
// | ||
// See the NOTICE file(s) distributed with this work for additional | ||
// information regarding copyright ownership. | ||
// | ||
// This program and the accompanying materials are made available under the | ||
// terms of the Apache Software License 2.0 which is available at | ||
// https://www.apache.org/licenses/LICENSE-2.0, or the MIT license | ||
// which is available at https://opensource.org/licenses/MIT. | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 OR MIT | ||
|
||
#include <iostream> | ||
|
||
#include "iox/duration.hpp" | ||
#include "iox2/node.hpp" | ||
#include "iox2/service_name.hpp" | ||
#include "iox2/service_type.hpp" | ||
#include "iox2/waitset.hpp" | ||
#include "pubsub_event.hpp" | ||
|
||
using namespace iox2; | ||
|
||
constexpr iox::units::Duration CYCLE_TIME = iox::units::Duration::fromMilliseconds(100); | ||
|
||
void find_and_cleanup_dead_nodes(); | ||
|
||
auto main() -> int { | ||
auto service_name_1 = ServiceName::create("service_1").expect(""); | ||
auto service_name_2 = ServiceName::create("service_2").expect(""); | ||
|
||
auto node = NodeBuilder() | ||
.name(NodeName::create("central daemon").expect("")) | ||
.create<ServiceType::Ipc>() | ||
.expect("successful node creation"); | ||
|
||
// The central daemon is responsible to create all services before hand and the other processes | ||
// just open the communication resources and start communicating. | ||
auto service_pubsub_1 = node.service_builder(service_name_1) | ||
.publish_subscribe<uint64_t>() | ||
// We use here open_or_create so that, in case of a crash of the central daemon, it can | ||
// be restarted. | ||
.open_or_create() | ||
.expect("successful service creation/opening"); | ||
|
||
auto service_event_1 = node.service_builder(service_name_1) | ||
.event() | ||
// Whenever a new notifier is created the PublisherConnected event is emitted. this makes | ||
// sense since in this example a notifier is always created after a new publisher was | ||
// created. | ||
// The task of the notifier/event is it to inform and wake up other processes when | ||
// certain system event have happened. | ||
.notifier_created_event(iox::into<EventId>(PubSubEvent::PublisherConnected)) | ||
.notifier_dropped_event(iox::into<EventId>(PubSubEvent::PublisherDisconnected)) | ||
// This event is emitted when either the central daemon or a decentralized process | ||
// detects a dead node and cleaned up all of its stale resources succesfully. | ||
.notifier_dead_event(iox::into<EventId>(PubSubEvent::ProcessDied)) | ||
.open_or_create() | ||
.expect("successful service creation/opening"); | ||
|
||
auto service_pubsub_2 = node.service_builder(service_name_2) | ||
.publish_subscribe<uint64_t>() | ||
.open_or_create() | ||
.expect("successful service creation/opening"); | ||
|
||
auto service_event_2 = node.service_builder(service_name_2) | ||
.event() | ||
.notifier_created_event(iox::into<EventId>(PubSubEvent::PublisherConnected)) | ||
.notifier_dropped_event(iox::into<EventId>(PubSubEvent::PublisherDisconnected)) | ||
.notifier_dead_event(iox::into<EventId>(PubSubEvent::ProcessDied)) | ||
.open_or_create() | ||
.expect("successful service creation/opening"); | ||
|
||
auto waitset = WaitSetBuilder().create<ServiceType::Ipc>().expect(""); | ||
auto cycle_guard = waitset.attach_interval(CYCLE_TIME); | ||
|
||
std::cout << "Central daemon up and running." << std::endl; | ||
waitset | ||
// The only task of our central daemon is it to monitor all running nodes and cleanup their | ||
// resources if a process has died. | ||
// | ||
// Since we added the notifier_dead_event to the service, all listeners, that are waiting | ||
// on a service where one participant has died, will be woken up and they receive | ||
// the PubSubEvent::ProcessDied | ||
.wait_and_process([](auto) { | ||
find_and_cleanup_dead_nodes(); | ||
return CallbackProgression::Continue; | ||
}) | ||
.expect(""); | ||
|
||
std::cout << "exit" << std::endl; | ||
|
||
return 0; | ||
} | ||
|
||
void find_and_cleanup_dead_nodes() { | ||
Node<ServiceType::Ipc>::list(Config::global_config(), [](auto node_state) { | ||
node_state.dead([](auto view) { | ||
std::cout << "detected dead node: "; | ||
view.details().and_then([](auto details) { std::cout << details.name().to_string().c_str(); }); | ||
std::cout << std::endl; | ||
view.remove_stale_resources().expect(""); | ||
}); | ||
return CallbackProgression::Continue; | ||
}).expect(""); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
// Copyright (c) 2024 Contributors to the Eclipse Foundation | ||
// | ||
// See the NOTICE file(s) distributed with this work for additional | ||
// information regarding copyright ownership. | ||
// | ||
// This program and the accompanying materials are made available under the | ||
// terms of the Apache Software License 2.0 which is available at | ||
// https://www.apache.org/licenses/LICENSE-2.0, or the MIT license | ||
// which is available at https://opensource.org/licenses/MIT. | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 OR MIT | ||
|
||
#include "iox/duration.hpp" | ||
#include "iox2/node.hpp" | ||
#include "iox2/service_name.hpp" | ||
#include "iox2/service_type.hpp" | ||
#include "iox2/waitset.hpp" | ||
#include "pubsub_event.hpp" | ||
|
||
#include <iostream> | ||
|
||
constexpr iox::units::Duration CYCLE_TIME = iox::units::Duration::fromMilliseconds(1000); | ||
|
||
auto main() -> int { | ||
using namespace iox2; | ||
auto service_name = ServiceName::create("service_1").expect(""); | ||
auto node = NodeBuilder() | ||
.name(NodeName::create("publisher 1").expect("")) | ||
.create<ServiceType::Ipc>() | ||
.expect("successful node creation"); | ||
|
||
auto service = open_service(node, service_name); | ||
|
||
auto publisher = service.pubsub.publisher_builder().create().expect(""); | ||
auto notifier = service.event | ||
.notifier_builder() | ||
// we only want to notify the other side explicitly when we have sent a sample | ||
// so we can define it as default event id | ||
.default_event_id(iox::into<EventId>(PubSubEvent::SentSample)) | ||
.create() | ||
.expect(""); | ||
auto counter = 0; | ||
|
||
auto waitset = WaitSetBuilder().create<ServiceType::Ipc>().expect(""); | ||
|
||
// we only want to notify the other side explicitly when we have sent a sample | ||
// so we can define it as default event id | ||
auto cycle_guard = waitset.attach_interval(CYCLE_TIME); | ||
|
||
waitset | ||
.wait_and_process([&](auto) { | ||
std::cout << service_name.to_string().c_str() << ": Send sample " << counter << " ..." << std::endl; | ||
publisher.send_copy(counter).expect(""); | ||
notifier.notify().expect(""); | ||
counter += 1; | ||
return CallbackProgression::Continue; | ||
}) | ||
.expect(""); | ||
|
||
std::cout << "exit" << std::endl; | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
// Copyright (c) 2024 Contributors to the Eclipse Foundation | ||
// | ||
// See the NOTICE file(s) distributed with this work for additional | ||
// information regarding copyright ownership. | ||
// | ||
// This program and the accompanying materials are made available under the | ||
// terms of the Apache Software License 2.0 which is available at | ||
// https://www.apache.org/licenses/LICENSE-2.0, or the MIT license | ||
// which is available at https://opensource.org/licenses/MIT. | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 OR MIT | ||
|
||
#include "iox/duration.hpp" | ||
#include "iox2/node.hpp" | ||
#include "iox2/service_name.hpp" | ||
#include "iox2/service_type.hpp" | ||
#include "iox2/waitset.hpp" | ||
#include "pubsub_event.hpp" | ||
|
||
#include <iostream> | ||
|
||
constexpr iox::units::Duration CYCLE_TIME = iox::units::Duration::fromMilliseconds(1500); | ||
|
||
auto main() -> int { | ||
using namespace iox2; | ||
auto service_name = ServiceName::create("service_2").expect(""); | ||
auto node = NodeBuilder() | ||
.name(NodeName::create("publisher 2").expect("")) | ||
.create<ServiceType::Ipc>() | ||
.expect("successful node creation"); | ||
|
||
auto service = open_service(node, service_name); | ||
|
||
auto publisher = service.pubsub.publisher_builder().create().expect(""); | ||
auto notifier = service.event | ||
.notifier_builder() | ||
// we only want to notify the other side explicitly when we have sent a sample | ||
// so we can define it as default event id | ||
.default_event_id(iox::into<EventId>(PubSubEvent::SentSample)) | ||
.create() | ||
.expect(""); | ||
auto counter = 1000000; // NOLINT, magic number is fine in an example | ||
|
||
auto waitset = WaitSetBuilder().create<ServiceType::Ipc>().expect(""); | ||
|
||
// we only want to notify the other side explicitly when we have sent a sample | ||
// so we can define it as default event id | ||
auto cycle_guard = waitset.attach_interval(CYCLE_TIME); | ||
|
||
waitset | ||
.wait_and_process([&](auto) { | ||
std::cout << service_name.to_string().c_str() << ": Send sample " << counter << " ..." << std::endl; | ||
publisher.send_copy(counter).expect(""); | ||
notifier.notify().expect(""); | ||
counter += 1; | ||
return CallbackProgression::Continue; | ||
}) | ||
.expect(""); | ||
|
||
std::cout << "exit" << std::endl; | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
// Copyright (c) 2024 Contributors to the Eclipse Foundation | ||
// | ||
// See the NOTICE file(s) distributed with this work for additional | ||
// information regarding copyright ownership. | ||
// | ||
// This program and the accompanying materials are made available under the | ||
// terms of the Apache Software License 2.0 which is available at | ||
// https://www.apache.org/licenses/LICENSE-2.0, or the MIT license | ||
// which is available at https://opensource.org/licenses/MIT. | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 OR MIT | ||
|
||
#ifndef __EXAMPLE_HEALTH_MONITORING_PUBSUB_EVENT_HPP__ | ||
#define __EXAMPLE_HEALTH_MONITORING_PUBSUB_EVENT_HPP__ | ||
|
||
#include "iox/into.hpp" | ||
#include "iox2/event_id.hpp" | ||
#include "iox2/node.hpp" | ||
#include "iox2/service_name.hpp" | ||
|
||
#include <cstdint> | ||
|
||
enum class PubSubEvent : uint8_t { | ||
PublisherConnected = 0, | ||
PublisherDisconnected = 1, | ||
SubscriberConnected = 2, | ||
SubscriberDisconnected = 3, | ||
SentSample = 4, | ||
ReceivedSample = 5, | ||
SentHistory = 6, | ||
ProcessDied = 7, | ||
Unknown, | ||
}; | ||
|
||
struct ServiceTuple { | ||
iox2::PortFactoryEvent<iox2::ServiceType::Ipc> event; | ||
iox2::PortFactoryPublishSubscribe<iox2::ServiceType::Ipc, uint64_t, void> pubsub; | ||
}; | ||
|
||
inline auto open_service(const iox2::Node<iox2::ServiceType::Ipc>& node, | ||
const iox2::ServiceName& service_name) -> ServiceTuple { | ||
auto service_pubsub = node.service_builder(service_name).publish_subscribe<uint64_t>().open().expect(""); | ||
auto service_event = node.service_builder(service_name).event().open().expect(""); | ||
|
||
return { std::move(service_event), std::move(service_pubsub) }; | ||
} | ||
|
||
namespace iox { | ||
template <> | ||
inline auto from<PubSubEvent, iox2::EventId>(const PubSubEvent value) noexcept -> iox2::EventId { | ||
return iox2::EventId(static_cast<uint64_t>(value)); | ||
} | ||
} // namespace iox | ||
|
||
|
||
#endif |
Oops, something went wrong.