From a58f6afa44e53ce3c5978bcea1b6fd5be9c9ef62 Mon Sep 17 00:00:00 2001 From: KerstinKeller Date: Wed, 10 Jul 2024 17:16:51 +0200 Subject: [PATCH 1/3] [core] Fix bug in frequency calculator that will reset the frequency to 0.0 even though data is still incoming. (#1650) --- ecal/core/src/util/frequency_calculator.h | 46 ++++++++++++------ ecal/tests/cpp/util_test/src/util_test.cpp | 55 +++++++++++++++++++++- 2 files changed, 85 insertions(+), 16 deletions(-) diff --git a/ecal/core/src/util/frequency_calculator.h b/ecal/core/src/util/frequency_calculator.h index 1ec85f4f04..05bda24a3f 100644 --- a/ecal/core/src/util/frequency_calculator.h +++ b/ecal/core/src/util/frequency_calculator.h @@ -1,6 +1,6 @@ -/* ========================= eCAL LICENSE ================================= +/* ========================= eCAL LICENSE ================================= * - * Copyright (C) 2016 - 2019 Continental Corporation + * Copyright (C) 2016 - 2024 Continental Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -52,8 +52,8 @@ namespace eCAL FrequencyCalculator(const time_point& now_) : counted_elements(0) - , first_tick(now_) - , last_tick(now_) + , first_tick_time(now_) + , last_tick_time(now_) , previous_frequency(0.0) { } @@ -61,7 +61,7 @@ namespace eCAL void addTick(const time_point& now) { counted_elements++; - last_tick = now; + last_tick_time = now; } double getFrequency() @@ -71,16 +71,16 @@ namespace eCAL return previous_frequency; } - previous_frequency = calculateFrequency(first_tick, last_tick, counted_elements); - first_tick = last_tick; + previous_frequency = calculateFrequency(first_tick_time, last_tick_time, counted_elements); + first_tick_time = last_tick_time; counted_elements = 0; return previous_frequency; } private: long long counted_elements; - time_point first_tick; - time_point last_tick; + time_point first_tick_time; + time_point last_tick_time; double previous_frequency; }; @@ -105,22 +105,37 @@ namespace eCAL { calculator->addTick(now); } - last_tick = now; + last_tick_time = now; + received_tick_since_get_frequency_called = true; } double getFrequency(const time_point& now) { double frequency = calculator ? calculator->getFrequency() : 0.0; + // if the frequency is 0.0, return it right away if (frequency == 0.0) { return 0.0; } - // calculate theoretical frequency to detect timeouts; - double theoretical_frequency = calculateFrequency(last_tick, now, 1); - // If the frequency is higher than reset_factor * theoretical_frequency, we reset. - if (frequency >= theoretical_frequency * reset_factor) + // if we have received ticks, this means we don't want to reset the calculation + // so we return the frequency that the calculator has calculated + if (received_tick_since_get_frequency_called) + { + received_tick_since_get_frequency_called = false; + return frequency; + } + + // if we have not received ticks since the last call of getFrequency + // then we calculate the ΔT, e.g. the timespan in seconds between last received and next incoming element + // Based on the last time we received a tick we could calculate when we expect the next tick + // We can also calculate when we want to time out, based on the reset factor + // timeout = last_tick + ΔT * reset_factor + // If the current time is greater than the timeout time, we reset the calculator and return 0 + auto expected_time_in_seconds_between_last_and_next_tick = std::chrono::duration(1 / frequency); + time_point timeout_time = last_tick_time + std::chrono::duration_cast(expected_time_in_seconds_between_last_and_next_tick * reset_factor); + if (now > timeout_time) { calculator.reset(); return 0.0; @@ -131,7 +146,8 @@ namespace eCAL private: float reset_factor; - time_point last_tick; + time_point last_tick_time; + bool received_tick_since_get_frequency_called = false; std::unique_ptr> calculator; }; } diff --git a/ecal/tests/cpp/util_test/src/util_test.cpp b/ecal/tests/cpp/util_test/src/util_test.cpp index abaf84d48f..5936dbf459 100644 --- a/ecal/tests/cpp/util_test/src/util_test.cpp +++ b/ecal/tests/cpp/util_test/src/util_test.cpp @@ -1,6 +1,6 @@ /* ========================= eCAL LICENSE ================================= * - * Copyright (C) 2016 - 2019 Continental Corporation + * Copyright (C) 2016 - 2024 Continental Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -194,3 +194,56 @@ TEST(core_cpp_util, Freq_ResettableFrequencyCalculator) } } } + + +struct command +{ + std::string command_type; + long long time_point; +}; + +std::vector commands = +{ +command{"getting frequency", 0 }, +command{"ticking", 500 }, +command{"getting frequency", 1000 }, +command{"ticking", 1500 }, +command{"getting frequency", 2000 }, +command{"ticking", 2500 }, +command{"getting frequency", 3000 }, +command{"ticking", 3998 }, +command{"getting frequency", 4000 }, +command{"ticking", 4002 }, +command{"getting frequency", 5000 }, +command{"ticking", 5998 }, +command{"getting frequency", 6000 }, +}; + +TEST(core_cpp_util, Freq_NoZeroFrequency) +{ + eCAL::ResettableFrequencyCalculator calculator(3.0f); + int i = 0; + + for (const auto& command : commands) + { + std::chrono::steady_clock::time_point time(std::chrono::milliseconds(command.time_point)); + + if (command.command_type == "ticking") + { + calculator.addTick(time); + } + else if (command.command_type == "getting frequency") + { + auto frequency = calculator.getFrequency(time); + if (i > 1) + { + ASSERT_GT(frequency, 0.0) << "Iteration " << i; + } + + ++i; + } + else + { + } + } +} From 4d67a9f85e51d179eb7e5b3a20c1a611148ef272 Mon Sep 17 00:00:00 2001 From: KerstinKeller Date: Fri, 12 Jul 2024 10:27:08 +0200 Subject: [PATCH 2/3] [core] registration provider refactoring (#1647) * Split logic for registration providers into different files. --- ecal/core/CMakeLists.txt | 7 + .../ecal_process_registration.cpp | 104 ++++++++ .../registration/ecal_process_registration.h | 37 +++ .../ecal_registration_provider.cpp | 230 +++--------------- .../registration/ecal_registration_provider.h | 46 +--- .../registration/ecal_registration_sender.h | 57 +++++ .../ecal_registration_sender_shm.cpp | 66 +++++ .../ecal_registration_sender_shm.h | 58 +++++ .../ecal_registration_sender_udp.cpp | 81 ++++++ .../ecal_registration_sender_udp.h | 55 +++++ 10 files changed, 511 insertions(+), 230 deletions(-) create mode 100644 ecal/core/src/registration/ecal_process_registration.cpp create mode 100644 ecal/core/src/registration/ecal_process_registration.h create mode 100644 ecal/core/src/registration/ecal_registration_sender.h create mode 100644 ecal/core/src/registration/ecal_registration_sender_shm.cpp create mode 100644 ecal/core/src/registration/ecal_registration_sender_shm.h create mode 100644 ecal/core/src/registration/ecal_registration_sender_udp.cpp create mode 100644 ecal/core/src/registration/ecal_registration_sender_udp.h diff --git a/ecal/core/CMakeLists.txt b/ecal/core/CMakeLists.txt index 699efdd52c..558419d689 100644 --- a/ecal/core/CMakeLists.txt +++ b/ecal/core/CMakeLists.txt @@ -278,15 +278,22 @@ endif() ###################################### if (ECAL_CORE_REGISTRATION) set(ecal_registration_src + src/registration/ecal_process_registration.cpp + src/registration/ecal_process_registration.h src/registration/ecal_registration_provider.cpp src/registration/ecal_registration_provider.h src/registration/ecal_registration_receiver.cpp src/registration/ecal_registration_receiver.h + src/registration/ecal_registration_sender.h + src/registration/ecal_registration_sender_udp.cpp + src/registration/ecal_registration_sender_udp.h ) if(ECAL_CORE_REGISTRATION_SHM) list(APPEND ecal_registration_src src/registration/ecal_registration_receiver_shm.cpp src/registration/ecal_registration_receiver_shm.h + src/registration/ecal_registration_sender_shm.cpp + src/registration/ecal_registration_sender_shm.h src/registration/shm/ecal_memfile_broadcast.cpp src/registration/shm/ecal_memfile_broadcast.h src/registration/shm/ecal_memfile_broadcast_reader.cpp diff --git a/ecal/core/src/registration/ecal_process_registration.cpp b/ecal/core/src/registration/ecal_process_registration.cpp new file mode 100644 index 0000000000..18ca56aa50 --- /dev/null +++ b/ecal/core/src/registration/ecal_process_registration.cpp @@ -0,0 +1,104 @@ +/* ========================= eCAL LICENSE ================================= + * + * Copyright (C) 2016 - 2024 Continental Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ========================= eCAL LICENSE ================================= +*/ + +/** + * @brief Functions to generate Process Registration / Unregistration samples. + * +**/ + +#include "ecal_process_registration.h" + +#include +#include +#include "ecal_global_accessors.h" +#include "ecal_globals.h" +#include "time/ecal_timegate.h" + +eCAL::Registration::Sample eCAL::Registration::GetProcessRegisterSample() +{ + Registration::Sample process_sample; + process_sample.cmd_type = bct_reg_process; + auto& process_sample_process = process_sample.process; + process_sample_process.hname = eCAL::Process::GetHostName(); + process_sample_process.hgname = eCAL::Process::GetHostGroupName(); + process_sample_process.pid = eCAL::Process::GetProcessID(); + process_sample_process.pname = eCAL::Process::GetProcessName(); + process_sample_process.uname = eCAL::Process::GetUnitName(); + process_sample_process.pparam = eCAL::Process::GetProcessParameter(); + process_sample_process.state.severity = static_cast(g_process_severity); + process_sample_process.state.severity_level = static_cast(g_process_severity_level); + process_sample_process.state.info = g_process_info; +#if ECAL_CORE_TIMEPLUGIN + if (g_timegate() == nullptr) + { + process_sample_process.tsync_state = Registration::eTSyncState::tsync_none; + } + else + { + if (!g_timegate()->IsSynchronized()) + { + process_sample_process.tsync_state = Registration::eTSyncState::tsync_none; + } + else + { + switch (g_timegate()->GetSyncMode()) + { + case CTimeGate::eTimeSyncMode::realtime: + process_sample_process.tsync_state = Registration::eTSyncState::tsync_realtime; + break; + case CTimeGate::eTimeSyncMode::replay: + process_sample_process.tsync_state = Registration::eTSyncState::tsync_replay; + break; + default: + process_sample_process.tsync_state = Registration::eTSyncState::tsync_none; + break; + } + } + process_sample_process.tsync_mod_name = g_timegate()->GetName(); + } +#endif + + // eCAL initialization state + const unsigned int comp_state(g_globals()->GetComponents()); + process_sample_process.component_init_state = static_cast(comp_state); + std::string component_info; + if ((comp_state & eCAL::Init::Publisher) != 0u) component_info += "|pub"; + if ((comp_state & eCAL::Init::Subscriber) != 0u) component_info += "|sub"; + if ((comp_state & eCAL::Init::Logging) != 0u) component_info += "|log"; + if ((comp_state & eCAL::Init::TimeSync) != 0u) component_info += "|time"; + if (!component_info.empty()) component_info = component_info.substr(1); + process_sample_process.component_init_info = component_info; + + process_sample_process.ecal_runtime_version = eCAL::GetVersionString(); + + return process_sample; +} + +eCAL::Registration::Sample eCAL::Registration::GetProcessUnregisterSample() +{ + Registration::Sample process_sample; + process_sample.cmd_type = bct_unreg_process; + auto& process_sample_process = process_sample.process; + process_sample_process.hname = eCAL::Process::GetHostName(); + process_sample_process.pid = eCAL::Process::GetProcessID(); + process_sample_process.pname = eCAL::Process::GetProcessName(); + process_sample_process.uname = eCAL::Process::GetUnitName(); + + return process_sample; +} diff --git a/ecal/core/src/registration/ecal_process_registration.h b/ecal/core/src/registration/ecal_process_registration.h new file mode 100644 index 0000000000..e5961f5f82 --- /dev/null +++ b/ecal/core/src/registration/ecal_process_registration.h @@ -0,0 +1,37 @@ +/* ========================= eCAL LICENSE ================================= + * + * Copyright (C) 2016 - 2024 Continental Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ========================= eCAL LICENSE ================================= +*/ + +/** + * @brief Functions to generate Process Registration / Unregistration samples. + * +**/ + +#pragma once + +#include "serialization/ecal_struct_sample_registration.h" + +namespace eCAL +{ + namespace Registration + { + Sample GetProcessRegisterSample(); + + Sample GetProcessUnregisterSample(); + } +} \ No newline at end of file diff --git a/ecal/core/src/registration/ecal_registration_provider.cpp b/ecal/core/src/registration/ecal_registration_provider.cpp index 15b836da8c..363ede8fde 100644 --- a/ecal/core/src/registration/ecal_registration_provider.cpp +++ b/ecal/core/src/registration/ecal_registration_provider.cpp @@ -25,17 +25,9 @@ * These information will be send cyclic (registration refresh) via UDP to external eCAL processes. * **/ - -#include -#include - -#include "ecal_def.h" -#include "ecal_globals.h" #include "ecal_registration_provider.h" -#include "io/udp/ecal_udp_configurations.h" -#include "io/udp/ecal_udp_sample_sender.h" - +#include #include #include #include @@ -43,6 +35,16 @@ #include #include +#include +#include +#include "ecal_def.h" + +#include +#include +#if ECAL_CORE_REGISTRATION_SHM +#include +#endif + namespace eCAL { std::atomic CRegistrationProvider::m_created; @@ -66,27 +68,17 @@ namespace eCAL m_use_registration_shm = Config::IsShmRegistrationEnabled(); m_use_registration_udp = !m_use_registration_shm; - if (m_use_registration_udp) - { - // set network attributes - eCAL::UDP::SSenderAttr attr; - attr.address = UDP::GetRegistrationAddress(); - attr.port = UDP::GetRegistrationPort(); - attr.ttl = UDP::GetMulticastTtl(); - attr.broadcast = UDP::IsBroadcast(); - attr.loopback = true; - attr.sndbuf = Config::GetUdpMulticastSndBufSizeBytes(); - - // create udp registration sender - m_reg_sample_snd = std::make_shared(attr); - } - + // TODO Create the registration sender #if ECAL_CORE_REGISTRATION_SHM if (m_use_registration_shm) { - std::cout << "Shared memory monitoring is enabled (domain: " << Config::Experimental::GetShmMonitoringDomain() << " - queue size: " << Config::Experimental::GetShmMonitoringQueueSize() << ")" << '\n'; - m_memfile_broadcast.Create(Config::Experimental::GetShmMonitoringDomain(), Config::Experimental::GetShmMonitoringQueueSize()); - m_memfile_broadcast_writer.Bind(&m_memfile_broadcast); + m_reg_sender = std::make_unique(); + } + else + { +#endif + m_reg_sender = std::make_unique(); +#if ECAL_CORE_REGISTRATION_SHM } #endif @@ -105,28 +97,11 @@ namespace eCAL m_reg_sample_snd_thread->stop(); // add process unregistration sample - AddSample2SampleList(GetProcessUnregisterSample()); + AddSample2SampleList(Registration::GetProcessUnregisterSample()); - if (m_use_registration_udp) - { - // send process unregistration sample over udp - SendSampleList2UDP(); + SendSampleList(); - // destroy udp registration sample sender - m_reg_sample_snd.reset(); - } - -#if ECAL_CORE_REGISTRATION_SHM - if (m_use_registration_shm) - { - // broadcast process unregistration sample over shm - SendSampleList2SHM(); - - // destroy shm registration sample writer - m_memfile_broadcast_writer.Unbind(); - m_memfile_broadcast.Destroy(); - } -#endif + m_reg_sender.reset(); m_created = false; } @@ -150,12 +125,14 @@ namespace eCAL // if registration is forced if (force_) { + SendSampleList(); + // send single registration sample over udp - SendSample2UDP(sample_); + //SendSample2UDP(sample_); #if ECAL_CORE_REGISTRATION_SHM // broadcast (updated) sample list over shm - SendSampleList2SHM(); + //SendSampleList2SHM(); #endif } @@ -184,72 +161,6 @@ namespace eCAL m_sample_list.samples.push_back(sample_); } - bool CRegistrationProvider::SendSample2UDP(const Registration::Sample& sample_) - { - if (!m_created) return(false); - - if (m_use_registration_udp && m_reg_sample_snd) - { - // lock sample buffer - const std::lock_guard lock(m_sample_buffer_mtx); - - // serialize single sample - if (SerializeToBuffer(sample_, m_sample_buffer)) - { - // send single sample over udp - return m_reg_sample_snd->Send("reg_sample", m_sample_buffer) != 0; - } - } - return(false); - } - - bool CRegistrationProvider::SendSampleList2UDP() - { - if (!m_created) return(false); - bool return_value{ true }; - - // lock sample list - const std::lock_guard lock(m_sample_list_mtx); - - // send all (single) samples over udp - if (m_use_registration_udp && m_reg_sample_snd) - { - for (const auto& sample : m_sample_list.samples) - { - return_value &= SendSample2UDP(sample); - } - } - - return return_value; - } - -#if ECAL_CORE_REGISTRATION_SHM - bool CRegistrationProvider::SendSampleList2SHM() - { - if (!m_created) return(false); - - bool return_value{ true }; - - // send sample list over shm - if (m_use_registration_shm) - { - // lock sample list - const std::lock_guard lock(m_sample_list_mtx); - - // serialize whole sample list - if (SerializeToBuffer(m_sample_list, m_sample_list_buffer)) - { - if (!m_sample_list_buffer.empty()) - { - // broadcast sample list over shm - return_value &= m_memfile_broadcast_writer.Write(m_sample_list_buffer.data(), m_sample_list_buffer.size()); - } - } - } - return return_value; - } -#endif - void CRegistrationProvider::ClearSampleList() { // lock sample list @@ -258,6 +169,12 @@ namespace eCAL m_sample_list.samples.clear(); } + void CRegistrationProvider::SendSampleList() + { + std::lock_guard lock(m_sample_list_mtx); + m_reg_sender->SendSampleList(m_sample_list); + } + void CRegistrationProvider::RegisterSendThread() { #if ECAL_CORE_SUBSCRIBER @@ -278,91 +195,12 @@ namespace eCAL if (g_clientgate() != nullptr) g_clientgate()->RefreshRegistrations(); #endif - // send out sample list over udp - SendSampleList2UDP(); - -#if ECAL_CORE_REGISTRATION_SHM - // broadcast sample list over shm - SendSampleList2SHM(); -#endif + SendSampleList(); // clear registration sample list ClearSampleList(); // add process registration sample to internal sample list as first sample (for next registration loop) - AddSample2SampleList(GetProcessRegisterSample()); - } - - Registration::Sample CRegistrationProvider::GetProcessRegisterSample() - { - Registration::Sample process_sample; - process_sample.cmd_type = bct_reg_process; - auto& process_sample_process = process_sample.process; - process_sample_process.hname = Process::GetHostName(); - process_sample_process.hgname = Process::GetHostGroupName(); - process_sample_process.pid = Process::GetProcessID(); - process_sample_process.pname = Process::GetProcessName(); - process_sample_process.uname = Process::GetUnitName(); - process_sample_process.pparam = Process::GetProcessParameter(); - process_sample_process.state.severity = static_cast(g_process_severity); - process_sample_process.state.severity_level = static_cast(g_process_severity_level); - process_sample_process.state.info = g_process_info; -#if ECAL_CORE_TIMEPLUGIN - if (g_timegate() == nullptr) - { - process_sample_process.tsync_state = Registration::eTSyncState::tsync_none; - } - else - { - if (!g_timegate()->IsSynchronized()) - { - process_sample_process.tsync_state = Registration::eTSyncState::tsync_none; - } - else - { - switch (g_timegate()->GetSyncMode()) - { - case CTimeGate::eTimeSyncMode::realtime: - process_sample_process.tsync_state = Registration::eTSyncState::tsync_realtime; - break; - case CTimeGate::eTimeSyncMode::replay: - process_sample_process.tsync_state = Registration::eTSyncState::tsync_replay; - break; - default: - process_sample_process.tsync_state = Registration::eTSyncState::tsync_none; - break; - } - } - process_sample_process.tsync_mod_name = g_timegate()->GetName(); - } -#endif - - // eCAL initialization state - const unsigned int comp_state(g_globals()->GetComponents()); - process_sample_process.component_init_state = static_cast(comp_state); - std::string component_info; - if ((comp_state & Init::Publisher) != 0u) component_info += "|pub"; - if ((comp_state & Init::Subscriber) != 0u) component_info += "|sub"; - if ((comp_state & Init::Logging) != 0u) component_info += "|log"; - if ((comp_state & Init::TimeSync) != 0u) component_info += "|time"; - if (!component_info.empty()) component_info = component_info.substr(1); - process_sample_process.component_init_info = component_info; - - process_sample_process.ecal_runtime_version = GetVersionString(); - - return process_sample; - } - - Registration::Sample CRegistrationProvider::GetProcessUnregisterSample() - { - Registration::Sample process_sample; - process_sample.cmd_type = bct_unreg_process; - auto& process_sample_process = process_sample.process; - process_sample_process.hname = Process::GetHostName(); - process_sample_process.pid = Process::GetProcessID(); - process_sample_process.pname = Process::GetProcessName(); - process_sample_process.uname = Process::GetUnitName(); - - return process_sample; + AddSample2SampleList(Registration::GetProcessRegisterSample()); } } diff --git a/ecal/core/src/registration/ecal_registration_provider.h b/ecal/core/src/registration/ecal_registration_provider.h index 098a9ef2da..422e65277e 100644 --- a/ecal/core/src/registration/ecal_registration_provider.h +++ b/ecal/core/src/registration/ecal_registration_provider.h @@ -30,21 +30,15 @@ #include "io/udp/ecal_udp_sample_sender.h" -#include "util/ecal_thread.h" - -#if ECAL_CORE_REGISTRATION_SHM -#include "shm/ecal_memfile_broadcast.h" -#include "shm/ecal_memfile_broadcast_writer.h" -#endif - -#include "serialization/ecal_serialize_sample_registration.h" - #include #include #include #include #include +#include +#include "util/ecal_thread.h" + namespace eCAL { class CRegistrationProvider @@ -64,40 +58,24 @@ namespace eCAL protected: void AddSample2SampleList(const Registration::Sample& sample_); - bool SendSample2UDP(const Registration::Sample& sample_); - - bool SendSampleList2UDP(); -#if ECAL_CORE_REGISTRATION_SHM - bool SendSampleList2SHM(); -#endif void ClearSampleList(); + void SendSampleList(); void RegisterSendThread(); - Registration::Sample GetProcessRegisterSample(); - Registration::Sample GetProcessUnregisterSample(); - - static std::atomic m_created; - - std::shared_ptr m_reg_sample_snd; - std::shared_ptr m_reg_sample_snd_thread; + static std::atomic m_created; - std::mutex m_sample_buffer_mtx; - std::vector m_sample_buffer; + std::unique_ptr m_reg_sender; - std::mutex m_sample_list_mtx; - Registration::SampleList m_sample_list; + std::shared_ptr m_reg_sample_snd_thread; -#if ECAL_CORE_REGISTRATION_SHM - std::vector m_sample_list_buffer; - CMemoryFileBroadcast m_memfile_broadcast; - CMemoryFileBroadcastWriter m_memfile_broadcast_writer; -#endif + std::mutex m_sample_list_mtx; + Registration::SampleList m_sample_list; - bool m_use_registration_udp; - bool m_use_registration_shm; + bool m_use_registration_udp; + bool m_use_registration_shm; - std::mutex m_callback_custom_apply_sample_map_mtx; + std::mutex m_callback_custom_apply_sample_map_mtx; std::map m_callback_custom_apply_sample_map; }; } diff --git a/ecal/core/src/registration/ecal_registration_sender.h b/ecal/core/src/registration/ecal_registration_sender.h new file mode 100644 index 0000000000..4f9d6e504f --- /dev/null +++ b/ecal/core/src/registration/ecal_registration_sender.h @@ -0,0 +1,57 @@ +/* ========================= eCAL LICENSE ================================= + * + * Copyright (C) 2016 - 2024 Continental Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ========================= eCAL LICENSE ================================= +*/ + +/** + * @brief eCAL registration provider + * + * All process internal publisher/subscriber, server/clients register here with all their attributes. + * + * These information will be send cyclic (registration refresh) via UDP to external eCAL processes. + * +**/ + +#pragma once + +#include "serialization/ecal_struct_sample_registration.h" + + +namespace eCAL +{ + class CRegistrationSender + { + public: + CRegistrationSender() = default; + virtual ~CRegistrationSender() = default; + + // Copy constructor + CRegistrationSender(const CRegistrationSender& other) = delete; + + // Copy assignment operator + CRegistrationSender& operator=(const CRegistrationSender & other) = delete; + + // Move constructor + CRegistrationSender(CRegistrationSender && other) noexcept = delete; + + // Move assignment operator + CRegistrationSender& operator=(CRegistrationSender && other) noexcept = delete; + + //virtual bool SendSample(const Registration::Sample& sample_) = 0; + virtual bool SendSampleList(const Registration::SampleList& sample_list) = 0; + }; +} diff --git a/ecal/core/src/registration/ecal_registration_sender_shm.cpp b/ecal/core/src/registration/ecal_registration_sender_shm.cpp new file mode 100644 index 0000000000..ddde350b36 --- /dev/null +++ b/ecal/core/src/registration/ecal_registration_sender_shm.cpp @@ -0,0 +1,66 @@ +/* ========================= eCAL LICENSE ================================= + * + * Copyright (C) 2016 - 2024 Continental Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ========================= eCAL LICENSE ================================= +*/ + +/** + * @brief eCAL registration provider + * + * All process internal publisher/subscriber, server/clients register here with all their attributes. + * + * These information will be send cyclic (registration refresh) via UDP to external eCAL processes. + * +**/ + +#include "registration/ecal_registration_sender_shm.h" +#include "serialization/ecal_serialize_sample_registration.h" + + +eCAL::CRegistrationSenderSHM::CRegistrationSenderSHM() +{ + std::cout << "Shared memory monitoring is enabled (domain: " << Config::Experimental::GetShmMonitoringDomain() << " - queue size: " << Config::Experimental::GetShmMonitoringQueueSize() << ")" << '\n'; + m_memfile_broadcast.Create(Config::Experimental::GetShmMonitoringDomain(), Config::Experimental::GetShmMonitoringQueueSize()); + m_memfile_broadcast_writer.Bind(&m_memfile_broadcast); +} + +eCAL::CRegistrationSenderSHM::~CRegistrationSenderSHM() +{ + m_memfile_broadcast_writer.Unbind(); + m_memfile_broadcast.Destroy(); +} + +/* +bool eCAL::CRegistrationSenderSHM::SendSample(const Registration::Sample& sample_) +{ + return false; +} +*/ + +bool eCAL::CRegistrationSenderSHM::SendSampleList(const Registration::SampleList& sample_list) +{ + bool return_value{true}; + // serialize whole sample list + if (SerializeToBuffer(sample_list, m_sample_list_buffer)) + { + if (!m_sample_list_buffer.empty()) + { + // broadcast sample list over shm + return_value &= m_memfile_broadcast_writer.Write(m_sample_list_buffer.data(), m_sample_list_buffer.size()); + } + } + return return_value; +} diff --git a/ecal/core/src/registration/ecal_registration_sender_shm.h b/ecal/core/src/registration/ecal_registration_sender_shm.h new file mode 100644 index 0000000000..266e644c89 --- /dev/null +++ b/ecal/core/src/registration/ecal_registration_sender_shm.h @@ -0,0 +1,58 @@ +/* ========================= eCAL LICENSE ================================= + * + * Copyright (C) 2016 - 2024 Continental Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ========================= eCAL LICENSE ================================= +*/ + +/** + * @brief eCAL registration provider + * + * All process internal publisher/subscriber, server/clients register here with all their attributes. + * + * These information will be send cyclic (registration refresh) via UDP to external eCAL processes. + * +**/ + +#pragma once + +#include "registration/ecal_registration_sender.h" + +#include "shm/ecal_memfile_broadcast.h" +#include "shm/ecal_memfile_broadcast_writer.h" + +namespace eCAL +{ + class CRegistrationSenderSHM : public CRegistrationSender + { + public: + CRegistrationSenderSHM(); + ~CRegistrationSenderSHM() override; + + // Special member functionss + CRegistrationSenderSHM(const CRegistrationSenderSHM& other) = delete; + CRegistrationSenderSHM& operator=(const CRegistrationSenderSHM& other) = delete; + CRegistrationSenderSHM(CRegistrationSenderSHM&& other) noexcept = delete; + CRegistrationSenderSHM& operator=(CRegistrationSenderSHM&& other) noexcept = delete; + + //bool SendSample(const Registration::Sample& sample_) override; + bool SendSampleList(const Registration::SampleList& sample_list) override; + + private: + std::vector m_sample_list_buffer; + CMemoryFileBroadcast m_memfile_broadcast; + CMemoryFileBroadcastWriter m_memfile_broadcast_writer; + }; +} \ No newline at end of file diff --git a/ecal/core/src/registration/ecal_registration_sender_udp.cpp b/ecal/core/src/registration/ecal_registration_sender_udp.cpp new file mode 100644 index 0000000000..0991483240 --- /dev/null +++ b/ecal/core/src/registration/ecal_registration_sender_udp.cpp @@ -0,0 +1,81 @@ +/* ========================= eCAL LICENSE ================================= + * + * Copyright (C) 2016 - 2024 Continental Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ========================= eCAL LICENSE ================================= +*/ + +/** + * @brief eCAL registration provider + * + * All process internal publisher/subscriber, server/clients register here with all their attributes. + * + * These information will be send cyclic (registration refresh) via UDP to external eCAL processes. + * +**/ + +#include "registration/ecal_registration_sender_udp.h" + +#include "serialization/ecal_serialize_sample_registration.h" +#include "io/udp/ecal_udp_configurations.h" +#include + +namespace +{ + using namespace eCAL; + UDP::SSenderAttr CreateAttributes() + { + eCAL::UDP::SSenderAttr attr; + attr.address = UDP::GetRegistrationAddress(); + attr.port = UDP::GetRegistrationPort(); + attr.ttl = UDP::GetMulticastTtl(); + attr.broadcast = UDP::IsBroadcast(); + attr.loopback = true; + attr.sndbuf = Config::GetUdpMulticastSndBufSizeBytes(); + return attr; + } + +} + +namespace eCAL +{ + CRegistrationSenderUDP::CRegistrationSenderUDP() + : m_reg_sample_snd(CreateAttributes()) + { + } + + CRegistrationSenderUDP::~CRegistrationSenderUDP() = default; + + bool CRegistrationSenderUDP::SendSample(const Registration::Sample& sample_) + { + // serialize single sample + if (SerializeToBuffer(sample_, m_sample_buffer)) + { + // send single sample over udp + return m_reg_sample_snd.Send("reg_sample", m_sample_buffer) != 0; + } + return false; + } + + bool CRegistrationSenderUDP::SendSampleList(const Registration::SampleList& sample_list) + { + bool return_value{ true }; + for (const auto& sample : sample_list.samples) + { + return_value &= SendSample(sample); + } + return return_value; + } +} \ No newline at end of file diff --git a/ecal/core/src/registration/ecal_registration_sender_udp.h b/ecal/core/src/registration/ecal_registration_sender_udp.h new file mode 100644 index 0000000000..65967cd1f9 --- /dev/null +++ b/ecal/core/src/registration/ecal_registration_sender_udp.h @@ -0,0 +1,55 @@ +/* ========================= eCAL LICENSE ================================= + * + * Copyright (C) 2016 - 2024 Continental Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ========================= eCAL LICENSE ================================= +*/ + +/** + * @brief eCAL registration sender UDP + * + * A device which sends out registration information via UDP + * +**/ + +#pragma once + +#include "registration/ecal_registration_sender.h" + +#include "io/udp/ecal_udp_sample_sender.h" + +namespace eCAL +{ + class CRegistrationSenderUDP : public CRegistrationSender + { + public: + CRegistrationSenderUDP(); + ~CRegistrationSenderUDP() override; + + // Special member functionss + CRegistrationSenderUDP(const CRegistrationSenderUDP& other) = delete; + CRegistrationSenderUDP& operator=(const CRegistrationSenderUDP& other) = delete; + CRegistrationSenderUDP(CRegistrationSenderUDP&& other) noexcept = delete; + CRegistrationSenderUDP& operator=(CRegistrationSenderUDP&& other) noexcept = delete; + + bool SendSampleList(const Registration::SampleList& sample_list) override; + + private: + bool SendSample(const Registration::Sample& sample_); + + UDP::CSampleSender m_reg_sample_snd; + std::vector m_sample_buffer; + }; +} \ No newline at end of file From a51ecec27958c2c7acf9ae4461f79bb2b1689f98 Mon Sep 17 00:00:00 2001 From: Rex Schilasky <49162693+rex-schilasky@users.noreply.github.com> Date: Mon, 15 Jul 2024 11:48:23 +0200 Subject: [PATCH 3/3] [core] innosetup-configuration-path-fix (#1656) * innosetup path fix "configuration" -> "_configuration" * innosetup path fix "configinstall" -> "_configinstall" --- cpack/innosetup/ecal_setup.iss.in | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cpack/innosetup/ecal_setup.iss.in b/cpack/innosetup/ecal_setup.iss.in index 78ef6be139..7d8c19a34e 100644 --- a/cpack/innosetup/ecal_setup.iss.in +++ b/cpack/innosetup/ecal_setup.iss.in @@ -1,6 +1,6 @@ ; ========================= eCAL LICENSE ================================= ; -; Copyright (C) 2016 - 2019 Continental Corporation +; Copyright (C) 2016 - 2024 Continental Corporation ; ; Licensed under the Apache License, Version 2.0 (the "License"); ; you may not use this file except in compliance with the License. @@ -75,9 +75,9 @@ Source: "{#ComponentStagingDir}\runtime\*"; DestDir: "{app}"; Fla Source: "{#ComponentStagingDir}\Unspecified\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: runtime Source: "{#ComponentStagingDir}\libraries\bin\*"; DestDir: "{app}\bin\"; Flags: ignoreversion recursesubdirs; Components: runtime -Source: "{#ComponentStagingDir}\configuration\cfg\ecal.ini"; DestDir: "{commonappdata}\eCAL\"; Tasks: not replaceconf; Flags: ignoreversion confirmoverwrite; Components: runtime -Source: "{#ComponentStagingDir}\configuration\cfg\ecal.ini"; DestDir: "{commonappdata}\eCAL\"; Tasks: replaceconf; Flags: ignoreversion; Components: runtime -Source: "{#ComponentStagingDir}\configuration\cfg\ecaltime.ini"; DestDir: "{commonappdata}\eCAL\"; Flags: ignoreversion; Components: runtime +Source: "{#ComponentStagingDir}\_configuration\cfg\ecal.ini"; DestDir: "{commonappdata}\eCAL\"; Tasks: not replaceconf; Flags: ignoreversion confirmoverwrite; Components: runtime +Source: "{#ComponentStagingDir}\_configuration\cfg\ecal.ini"; DestDir: "{commonappdata}\eCAL\"; Tasks: replaceconf; Flags: ignoreversion; Components: runtime +Source: "{#ComponentStagingDir}\_configuration\cfg\ecaltime.ini"; DestDir: "{commonappdata}\eCAL\"; Flags: ignoreversion; Components: runtime ; applications Source: "{#ComponentStagingDir}\app\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: applications @@ -118,11 +118,11 @@ Source: "{#DebugSdkStagingDir}\protobuf-export\*"; DestDir: "{app}"; ; Source: "{#DebugSdkStagingDir}\protoc\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: sdk\protobuf ; sdk\hdf5 -Source: "{#ComponentStagingDir}\configinstall\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: sdk\hdf5 +Source: "{#ComponentStagingDir}\_configinstall\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: sdk\hdf5 Source: "{#ComponentStagingDir}\headers\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: sdk\hdf5 Source: "{#ComponentStagingDir}\libraries\lib\*"; DestDir: "{app}\lib"; Flags: ignoreversion recursesubdirs; Components: sdk\hdf5 -Source: "{#DebugSdkStagingDir}\configinstall\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: sdk\hdf5 +Source: "{#DebugSdkStagingDir}\_configinstall\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs; Components: sdk\hdf5 Source: "{#DebugSdkStagingDir}\libraries\lib\*"; DestDir: "{app}\lib"; Flags: ignoreversion recursesubdirs; Components: sdk\hdf5 Source: "{#DebugSdkStagingDir}\libraries\bin\*"; DestDir: "{app}\bin\"; Flags: ignoreversion recursesubdirs; Components: sdk\hdf5