From 6b6cf040ebaf064171b7a329477b40bc5677255e Mon Sep 17 00:00:00 2001 From: rex-schilasky <49162693+rex-schilasky@users.noreply.github.com> Date: Wed, 10 Apr 2024 11:09:28 +0200 Subject: [PATCH 01/27] topic, clients, services get unregistered actively from DescGate --- .../core/include/ecal/cimpl/ecal_util_cimpl.h | 51 ++++ ecal/core/include/ecal/ecal_util.h | 41 ++- ecal/core/src/cimpl/ecal_util_cimpl.cpp | 56 ++++ ecal/core/src/ecal_descgate.cpp | 273 +++++++++++++----- ecal/core/src/ecal_descgate.h | 49 +++- ecal/core/src/ecal_util.cpp | 28 +- .../src/monitoring_get_services.cpp | 4 +- .../cpp/clientserver_test/CMakeLists.txt | 1 - ecal/tests/cpp/pubsub_test/CMakeLists.txt | 1 - ecal/tests/cpp/util_test/CMakeLists.txt | 4 + .../cpp/util_test/src/util_getclients.cpp | 160 ++++++++++ .../src/util_getservices.cpp} | 12 +- .../src/util_gettopics.cpp} | 87 +++++- ecal/tests/cpp/util_test/src/util_test.cpp | 67 ----- 14 files changed, 647 insertions(+), 187 deletions(-) create mode 100644 ecal/tests/cpp/util_test/src/util_getclients.cpp rename ecal/tests/cpp/{clientserver_test/src/clientserver_getservices.cpp => util_test/src/util_getservices.cpp} (92%) rename ecal/tests/cpp/{pubsub_test/src/pubsub_gettopics.cpp => util_test/src/util_gettopics.cpp} (61%) diff --git a/ecal/core/include/ecal/cimpl/ecal_util_cimpl.h b/ecal/core/include/ecal/cimpl/ecal_util_cimpl.h index aa279f973c..d5d0cb2f09 100644 --- a/ecal/core/include/ecal/cimpl/ecal_util_cimpl.h +++ b/ecal/core/include/ecal/cimpl/ecal_util_cimpl.h @@ -151,6 +151,57 @@ extern "C" * @return Response description buffer length or zero if failed. **/ ECALC_API int eCAL_Util_GetServiceResponseDescription(const char* service_name_, const char* method_name_, void* resp_desc_, int resp_desc_len_); + + /** + * @brief Gets client method request type name. + * + * @param client_name_ Client name. + * @param method_name_ Method name. + * @param [out] req_type_ Pointer to store the request type. + * @param req_type_len_ Length of allocated buffer or ECAL_ALLOCATE_4ME if + * eCAL should allocate the buffer for you (see eCAL_FreeMem). + * + * @return Type name buffer length or zero if failed. + **/ + ECALC_API int eCAL_Util_GetClientRequestTypeName(const char* client_name_, const char* method_name_, void* req_type_, int req_type_len_); + + /** + * @brief Gets client method response type name. + * + * @param client_name_ Client name. + * @param method_name_ Method name. + * @param [out] resp_type_ Pointer to store the response type. + * @param resp_type_len_ Length of allocated buffer or ECAL_ALLOCATE_4ME if + * + * @return Type name buffer length or zero if failed. + **/ + ECALC_API int eCAL_Util_GetClientResponseTypeName(const char* client_name_, const char* method_name_, void* resp_type_, int resp_type_len_); + + /** + * @brief Gets client method request description. + * + * @param client_name_ Client name. + * @param method_name_ Method name. + * @param [out] req_desc_ Pointer to store the request description. + * @param req_desc_len_ Length of allocated buffer or ECAL_ALLOCATE_4ME if + * eCAL should allocate the buffer for you (see eCAL_FreeMem). + * + * @return Request description buffer length or zero if failed. + **/ + ECALC_API int eCAL_Util_GetClientRequestDescription(const char* client_name_, const char* method_name_, void* req_desc_, int req_desc_len_); + + /** + * @brief Gets client method response description. + * + * @param client_name_ Client name. + * @param method_name_ Method name. + * @param [out] resp_desc_ Pointer to store the response description. + * @param resp_desc_len_ Length of allocated buffer or ECAL_ALLOCATE_4ME if + * eCAL should allocate the buffer for you (see eCAL_FreeMem). + * + * @return Response description buffer length or zero if failed. + **/ + ECALC_API int eCAL_Util_GetClientResponseDescription(const char* client_name_, const char* method_name_, void* resp_desc_, int resp_desc_len_); #ifdef __cplusplus } #endif /*__cplusplus*/ diff --git a/ecal/core/include/ecal/ecal_util.h b/ecal/core/include/ecal/ecal_util.h index a6340311ca..9a258d4587 100644 --- a/ecal/core/include/ecal/ecal_util.h +++ b/ecal/core/include/ecal/ecal_util.h @@ -161,7 +161,7 @@ namespace eCAL * * @param service_method_names_ Vector to store the service/method tuples (Vector { (ServiceName, MethodName) }). **/ - ECAL_API void GetServiceNames(std::vector>& service_method_names_); + ECAL_API void GetServiceMethodNames(std::vector>& service_method_names_); /** * @brief Gets service method request and response type names. @@ -187,6 +187,45 @@ namespace eCAL **/ ECAL_API bool GetServiceDescription(const std::string& service_name_, const std::string& method_name_, std::string& req_desc_, std::string& resp_desc_); + /** + * @brief Get complete client map (including request and response types and descriptions). + * + * @param client_info_map_ Map to store the datatype descriptions. + * Map { (ClientName, MethodName) -> ( (ReqType, ReqDescription), (RespType, RespDescription) ) } mapping of all currently known clients. + **/ + ECAL_API void GetClients(std::map, SServiceMethodInformation>& client_info_map_); + + /** + * @brief Get all client/method names. + * + * @param client_method_names_ Vector to store the client/method tuples (Vector { (ClientName, MethodName) }). + **/ + ECAL_API void GetClientMethodNames(std::vector>& client_method_names_); + + /** + * @brief Gets client method request and response type names. + * + * @param client_name_ Client name. + * @param method_name_ Method name. + * @param req_type_ String to store request type. + * @param resp_type_ String to store response type. + * + * @return True if succeeded. + **/ + ECAL_API bool GetClientTypeNames(const std::string& client_name_, const std::string& method_name_, std::string& req_type_, std::string& resp_type_); + + /** + * @brief Gets client method request and response descriptions. + * + * @param client_name_ Client name. + * @param method_name_ Method name. + * @param req_desc_ String to store request description. + * @param resp_desc_ String to store response description. + * + * @return True if succeeded. + **/ + ECAL_API bool GetClientDescription(const std::string& client_name_, const std::string& method_name_, std::string& req_desc_, std::string& resp_desc_); + /** * @brief Splits the topic type (eCAL < 5.12) into encoding and types (>= eCAL 5.12) * diff --git a/ecal/core/src/cimpl/ecal_util_cimpl.cpp b/ecal/core/src/cimpl/ecal_util_cimpl.cpp index 5e0fffc568..da01819ac9 100644 --- a/ecal/core/src/cimpl/ecal_util_cimpl.cpp +++ b/ecal/core/src/cimpl/ecal_util_cimpl.cpp @@ -148,4 +148,60 @@ extern "C" } return 0; } + + ECALC_API int eCAL_Util_GetClientRequestTypeName(const char* client_name_, const char* method_name_, void* req_type_, int req_type_len_) + { + if (client_name_ == nullptr) return(0); + if (method_name_ == nullptr) return(0); + if (req_type_ == nullptr) return(0); + std::string req_type; + std::string resp_type; + if (eCAL::Util::GetClientTypeNames(client_name_, method_name_, req_type, resp_type)) + { + return(CopyBuffer(req_type_, req_type_len_, req_type)); + } + return 0; + } + + ECALC_API int eCAL_Util_GetClientResponseTypeName(const char* client_name_, const char* method_name_, void* resp_type_, int resp_type_len_) + { + if (client_name_ == nullptr) return(0); + if (method_name_ == nullptr) return(0); + if (resp_type_ == nullptr) return(0); + std::string req_type; + std::string resp_type; + if (eCAL::Util::GetClientTypeNames(client_name_, method_name_, req_type, resp_type)) + { + return(CopyBuffer(resp_type_, resp_type_len_, resp_type)); + } + return 0; + } + + ECALC_API int eCAL_Util_GetClientRequestDescription(const char* client_name_, const char* method_name_, void* req_desc_, int req_desc_len_) + { + if (client_name_ == nullptr) return(0); + if (method_name_ == nullptr) return(0); + if (req_desc_ == nullptr) return(0); + std::string req_desc; + std::string resp_desc; + if (eCAL::Util::GetClientDescription(client_name_, method_name_, req_desc, resp_desc)) + { + return(CopyBuffer(req_desc_, req_desc_len_, req_desc)); + } + return 0; + } + + ECALC_API int eCAL_Util_GetClientResponseDescription(const char* client_name_, const char* method_name_, void* resp_desc_, int resp_desc_len_) + { + if (client_name_ == nullptr) return(0); + if (method_name_ == nullptr) return(0); + if (resp_desc_ == nullptr) return(0); + std::string req_desc; + std::string resp_desc; + if (eCAL::Util::GetClientDescription(client_name_, method_name_, req_desc, resp_desc)) + { + return(CopyBuffer(resp_desc_, resp_desc_len_, resp_desc)); + } + return 0; + } } diff --git a/ecal/core/src/ecal_descgate.cpp b/ecal/core/src/ecal_descgate.cpp index a10d996197..08878df508 100644 --- a/ecal/core/src/ecal_descgate.cpp +++ b/ecal/core/src/ecal_descgate.cpp @@ -39,10 +39,24 @@ namespace quality |= eCAL::CDescGate::QualityFlags::TYPE_AVAILABLE; if (!(request_info_.descriptor.empty() && response_info_.descriptor.empty())) quality |= eCAL::CDescGate::QualityFlags::DESCRIPTION_AVAILABLE; + quality |= eCAL::CDescGate::QualityFlags::INFO_COMES_FROM_PRODUCER; return quality; } + // TODO: remove me with new CDescGate + eCAL::CDescGate::QualityFlags GetClientMethodQuality(const eCAL::SDataTypeInformation& request_info_, const eCAL::SDataTypeInformation& response_info_) + { + eCAL::CDescGate::QualityFlags quality = eCAL::CDescGate::QualityFlags::NO_QUALITY; + if (!(request_info_.name.empty() && response_info_.name.empty())) + quality |= eCAL::CDescGate::QualityFlags::TYPE_AVAILABLE; + if (!(request_info_.descriptor.empty() && response_info_.descriptor.empty())) + quality |= eCAL::CDescGate::QualityFlags::DESCRIPTION_AVAILABLE; + + return quality; + } + + // TODO: remove me with new CDescGate eCAL::CDescGate::QualityFlags GetPublisherQuality(const eCAL::SDataTypeInformation& topic_info_) { eCAL::CDescGate::QualityFlags quality = eCAL::CDescGate::QualityFlags::NO_QUALITY; @@ -56,6 +70,7 @@ namespace return quality; } + // TODO: remove me with new CDescGate eCAL::CDescGate::QualityFlags GetSubscriberQuality(const eCAL::SDataTypeInformation& topic_info_) { eCAL::CDescGate::QualityFlags quality = eCAL::CDescGate::QualityFlags::NO_QUALITY; @@ -73,7 +88,8 @@ namespace eCAL { CDescGate::CDescGate() : m_topic_info_map(std::chrono::milliseconds(Config::GetMonitoringTimeoutMs())), - m_service_info_map(std::chrono::milliseconds(Config::GetMonitoringTimeoutMs())) + m_service_info_map(std::chrono::milliseconds(Config::GetMonitoringTimeoutMs())), + m_client_info_map(std::chrono::milliseconds(Config::GetMonitoringTimeoutMs())) { } CDescGate::~CDescGate() = default; @@ -140,58 +156,42 @@ namespace eCAL void CDescGate::GetServices(std::map, SServiceMethodInformation>& service_info_map_) { - std::map, SServiceMethodInformation> map; - - const std::lock_guard lock(m_service_info_map.sync); - m_service_info_map.map->remove_deprecated(); - - for (const auto& service_info : (*m_service_info_map.map)) - { - map.emplace(service_info.first, service_info.second.info); - } - service_info_map_.swap(map); + GetServices(service_info_map_, m_service_info_map); } - void CDescGate::GetServiceNames(std::vector>& service_method_names_) + void CDescGate::GetServiceMethodNames(std::vector>& service_method_names_) { - service_method_names_.clear(); - - const std::lock_guard lock(m_service_info_map.sync); - m_service_info_map.map->remove_deprecated(); - service_method_names_.reserve(m_service_info_map.map->size()); - - for (const auto& service_info : (*m_service_info_map.map)) - { - service_method_names_.emplace_back(service_info.first); - } + GetServiceMethodNames(service_method_names_, m_service_info_map); } bool CDescGate::GetServiceTypeNames(const std::string& service_name_, const std::string& method_name_, std::string& req_type_name_, std::string& resp_type_name_) { - std::tuple service_method_tuple = std::make_tuple(service_name_, method_name_); + return GetServiceTypeNames(service_name_, method_name_, req_type_name_, resp_type_name_, m_service_info_map); + } - const std::lock_guard lock(m_service_info_map.sync); - m_service_info_map.map->remove_deprecated(); - auto service_info_map_it = m_service_info_map.map->find(service_method_tuple); + bool CDescGate::GetServiceDescription(const std::string& service_name_, const std::string& method_name_, std::string& req_type_desc_, std::string& resp_type_desc_) + { + return GetServiceDescription(service_name_, method_name_, req_type_desc_, resp_type_desc_, m_service_info_map); + } - if (service_info_map_it == m_service_info_map.map->end()) return false; - req_type_name_ = (*service_info_map_it).second.info.request_type.name; - resp_type_name_ = (*service_info_map_it).second.info.response_type.name; - return true; + void CDescGate::GetClients(std::map, SServiceMethodInformation>& service_info_map_) + { + GetServices(service_info_map_, m_client_info_map); } - bool CDescGate::GetServiceDescription(const std::string& service_name_, const std::string& method_name_, std::string& req_type_desc_, std::string& resp_type_desc_) + void CDescGate::GetClientMethodNames(std::vector>& client_method_names_) { - std::tuple service_method_tuple = std::make_tuple(service_name_, method_name_); + GetServiceMethodNames(client_method_names_, m_client_info_map); + } - const std::lock_guard lock(m_service_info_map.sync); - m_service_info_map.map->remove_deprecated(); - auto service_info_map_it = m_service_info_map.map->find(service_method_tuple); + bool CDescGate::GetClientTypeNames(const std::string& service_name_, const std::string& method_name_, std::string& req_type_name_, std::string& resp_type_name_) + { + return GetServiceTypeNames(service_name_, method_name_, req_type_name_, resp_type_name_, m_client_info_map); + } - if (service_info_map_it == m_service_info_map.map->end()) return false; - req_type_desc_ = (*service_info_map_it).second.info.request_type.descriptor; - resp_type_desc_ = (*service_info_map_it).second.info.response_type.descriptor; - return true; + bool CDescGate::GetClientDescription(const std::string& service_name_, const std::string& method_name_, std::string& req_type_desc_, std::string& resp_type_desc_) + { + return GetServiceDescription(service_name_, method_name_, req_type_desc_, resp_type_desc_, m_client_info_map); } bool CDescGate::ApplySample(const Registration::Sample& sample_, eTLayerType /*layer_*/) @@ -215,42 +215,41 @@ namespace eCAL response_type.name = method.resp_type; response_type.descriptor = method.resp_desc; - ApplyServiceDescription(sample_.service.sname, method.mname, request_type, response_type, GetServiceMethodQuality(request_type, response_type)); + ApplyServiceDescription(m_service_info_map, sample_.service.sname, sample_.service.sid, method.mname, request_type, response_type, GetServiceMethodQuality(request_type, response_type)); } } break; case bct_unreg_service: - // TODO: Implement fast unregistration + RemServiceDescription(m_service_info_map, sample_.service.sname, sample_.service.sid); break; case bct_reg_client: - // TODO: Implement this after client methods are available - //for (const auto& method : sample_.client.methods) - //{ - // SDataTypeInformation request_type; - // request_type.name = method.req_type; - // request_type.descriptor = method.req_desc; - - // SDataTypeInformation response_type{}; - // response_type.name = method.resp_type; - // response_type.descriptor = method.resp_desc; - - // ApplyClientDescription(sample_.service.sname, method.mname, request_type, response_type, GetQuality(sample_)); - //} + for (const auto& method : sample_.client.methods) + { + SDataTypeInformation request_type; + request_type.name = method.req_type; + request_type.descriptor = method.req_desc; + + SDataTypeInformation response_type{}; + response_type.name = method.resp_type; + response_type.descriptor = method.resp_desc; + + ApplyServiceDescription(m_client_info_map, sample_.client.sname, sample_.client.sid, method.mname, request_type, response_type, GetClientMethodQuality(request_type, response_type)); + } break; case bct_unreg_client: - // TODO: Implement fast unregistration + RemServiceDescription(m_client_info_map, sample_.client.sname, sample_.client.sid); break; case bct_reg_publisher: - ApplyTopicDescription(sample_.topic.tname, sample_.topic.tdatatype, GetPublisherQuality(sample_.topic.tdatatype)); + ApplyTopicDescription(sample_.topic.tname, sample_.topic.tid, sample_.topic.tdatatype, GetPublisherQuality(sample_.topic.tdatatype)); break; case bct_unreg_publisher: - // TODO: Implement fast unregistration + RemTopicDescription(sample_.topic.tname, sample_.topic.tid); break; case bct_reg_subscriber: - ApplyTopicDescription(sample_.topic.tname, sample_.topic.tdatatype, GetSubscriberQuality(sample_.topic.tdatatype)); + ApplyTopicDescription(sample_.topic.tname, sample_.topic.tid, sample_.topic.tdatatype, GetSubscriberQuality(sample_.topic.tdatatype)); break; case bct_unreg_subscriber: - // TODO: Implement fast unregistration + RemTopicDescription(sample_.topic.tname, sample_.topic.tid); break; default: { @@ -262,7 +261,7 @@ namespace eCAL return true; } - bool CDescGate::ApplyTopicDescription(const std::string& topic_name_, const SDataTypeInformation& topic_info_, const QualityFlags description_quality_) + bool CDescGate::ApplyTopicDescription(const std::string& topic_name_, const std::string& topic_id_, const SDataTypeInformation& topic_info_, const QualityFlags description_quality_) { const std::unique_lock lock(m_topic_info_map.sync); m_topic_info_map.map->remove_deprecated(); @@ -274,6 +273,7 @@ namespace eCAL { // create a new topic entry STopicInfoQuality& topic_info = (*m_topic_info_map.map)[topic_name_]; + topic_info.id = topic_id_; topic_info.info = topic_info_; topic_info.quality = description_quality_; return true; @@ -294,6 +294,7 @@ namespace eCAL if (description_quality_ > topic_info.quality) { // overwrite attributes + topic_info.id = topic_id_; topic_info.info = topic_info_; topic_info.quality = description_quality_; @@ -303,6 +304,7 @@ namespace eCAL } // this is the same topic (topic name, topic type name, topic type description) + // independing from the unique id if (topic_info.info == topic_info_) { // update timestamp (by just accessing the entry) and return @@ -402,7 +404,27 @@ namespace eCAL return false; } - bool CDescGate::ApplyServiceDescription(const std::string& service_name_ + bool CDescGate::RemTopicDescription(const std::string& topic_name_, const std::string& topic_id_) + { + const std::unique_lock lock(m_topic_info_map.sync); + m_topic_info_map.map->remove_deprecated(); + + const auto topic_info_it = m_topic_info_map.map->find(topic_name_); + if (topic_info_it != m_topic_info_map.map->end()) + { + STopicInfoQuality& topic_info = (*m_topic_info_map.map)[topic_name_]; + if (topic_info.id == topic_id_) + { + m_topic_info_map.map->erase(topic_name_); + return true; + } + } + return false; + } + + bool CDescGate::ApplyServiceDescription(SServiceMethodInfoMap& service_method_map_ + , const std::string& service_name_ + , const std::string& service_id_ , const std::string& method_name_ , const SDataTypeInformation& request_type_information_ , const SDataTypeInformation& response_type_information_ @@ -410,35 +432,126 @@ namespace eCAL { std::tuple service_method_tuple = std::make_tuple(service_name_, method_name_); - const std::lock_guard lock(m_service_info_map.sync); - m_service_info_map.map->remove_deprecated(); + const std::lock_guard lock(service_method_map_.sync); + service_method_map_.map->remove_deprecated(); + + SServiceMethodInfoQuality req_service_info; + req_service_info.id = service_id_; + req_service_info.info.request_type = request_type_information_; + req_service_info.info.response_type = response_type_information_; + req_service_info.quality = description_quality_; - auto service_info_map_it = m_service_info_map.map->find(service_method_tuple); - if (service_info_map_it == m_service_info_map.map->end()) + // create a new entry if service is not existing and return + auto service_info_map_it = service_method_map_.map->find(service_method_tuple); + if (service_info_map_it == service_method_map_.map->end()) { - // create a new service entry - SServiceMethodInfoQuality& service_info = (*m_service_info_map.map)[service_method_tuple]; - service_info.info.request_type = request_type_information_; - service_info.info.response_type = response_type_information_; - service_info.quality = description_quality_; + (*service_method_map_.map)[service_method_tuple] = req_service_info; return true; } - // let's check whether the current information has a higher quality - // if it has a higher quality, we overwrite it - bool ret_value(false); + // service is existing, the requested service has a higher quality + // overwrite the existing entry with the new attributes SServiceMethodInfoQuality service_info = (*service_info_map_it).second; if (description_quality_ > service_info.quality) { - service_info.info.request_type = request_type_information_; - service_info.info.response_type = response_type_information_; - service_info.quality = description_quality_; - ret_value = true; + (*service_method_map_.map)[service_method_tuple] = req_service_info; + return true; + } + + // the entry is existing, the requested quality is not higher + // update the existing entry if it has the same attributes (independing from the unique id) + if (service_info.info == req_service_info.info) + { + (*service_method_map_.map)[service_method_tuple] = req_service_info; + return true; + } + + return false; + } + + bool CDescGate::RemServiceDescription(SServiceMethodInfoMap& service_method_map_, const std::string& service_name_, const std::string& service_id_) + { + std::list> service_method_tuple_to_remove; + + const std::lock_guard lock(service_method_map_.sync); + service_method_map_.map->remove_deprecated(); + + bool success(false); + for (auto&& service : *service_method_map_.map) + { + auto service_method_tuple = service.first; + if (std::get<0>(service_method_tuple) == service_name_) + { + auto service_info = service.second; + if (service_info.id == service_id_) + { + service_method_tuple_to_remove.push_back(service_method_tuple); + success = true; + } + } + } + + for (const auto& service_method_tuple : service_method_tuple_to_remove) + { + (*service_method_map_.map).erase(service_method_tuple); + } + + return success; + } + + void CDescGate::GetServices(std::map, SServiceMethodInformation>& service_info_map_, const SServiceMethodInfoMap& service_method_map_) + { + std::map, SServiceMethodInformation> map; + + const std::lock_guard lock(service_method_map_.sync); + service_method_map_.map->remove_deprecated(); + + for (const auto& service_info : (*service_method_map_.map)) + { + map.emplace(service_info.first, service_info.second.info); } + service_info_map_.swap(map); + } + + void CDescGate::GetServiceMethodNames(std::vector>& method_names_, const SServiceMethodInfoMap& service_method_map_) + { + method_names_.clear(); + + const std::lock_guard lock(service_method_map_.sync); + service_method_map_.map->remove_deprecated(); + method_names_.reserve(service_method_map_.map->size()); - // update service entry (and its timestamp) - (*m_service_info_map.map)[service_method_tuple] = service_info; + for (const auto& service_info : (*service_method_map_.map)) + { + method_names_.emplace_back(service_info.first); + } + } - return ret_value; + bool CDescGate::GetServiceTypeNames(const std::string& service_name_, const std::string& method_name_, std::string& req_type_name_, std::string& resp_type_name_, const SServiceMethodInfoMap& service_method_map_) + { + std::tuple service_method_tuple = std::make_tuple(service_name_, method_name_); + + const std::lock_guard lock(service_method_map_.sync); + service_method_map_.map->remove_deprecated(); + auto service_info_map_it = service_method_map_.map->find(service_method_tuple); + + if (service_info_map_it == service_method_map_.map->end()) return false; + req_type_name_ = (*service_info_map_it).second.info.request_type.name; + resp_type_name_ = (*service_info_map_it).second.info.response_type.name; + return true; + } + + bool CDescGate::GetServiceDescription(const std::string& service_name_, const std::string& method_name_, std::string& req_type_desc_, std::string& resp_type_desc_, const SServiceMethodInfoMap& service_method_map_) + { + std::tuple service_method_tuple = std::make_tuple(service_name_, method_name_); + + const std::lock_guard lock(service_method_map_.sync); + service_method_map_.map->remove_deprecated(); + auto service_info_map_it = service_method_map_.map->find(service_method_tuple); + + if (service_info_map_it == service_method_map_.map->end()) return false; + req_type_desc_ = (*service_info_map_it).second.info.request_type.descriptor; + resp_type_desc_ = (*service_info_map_it).second.info.response_type.descriptor; + return true; } } diff --git a/ecal/core/src/ecal_descgate.h b/ecal/core/src/ecal_descgate.h index 6a95b398bb..571ff37436 100644 --- a/ecal/core/src/ecal_descgate.h +++ b/ecal/core/src/ecal_descgate.h @@ -72,26 +72,20 @@ namespace eCAL bool GetDataTypeInformation(const std::string& topic_name_, SDataTypeInformation& topic_info_); void GetServices(std::map, SServiceMethodInformation>& service_info_map_); - void GetServiceNames(std::vector>& service_method_names_); + void GetServiceMethodNames(std::vector>& service_method_names_); bool GetServiceTypeNames(const std::string& service_name_, const std::string& method_name_, std::string& req_type_name_, std::string& resp_type_name_); bool GetServiceDescription(const std::string& service_name_, const std::string& method_name_, std::string& req_type_desc_, std::string& resp_type_desc_); - protected: - bool ApplySample(const Registration::Sample& sample_, eTLayerType layer_); - - bool ApplyTopicDescription(const std::string& topic_name_, - const SDataTypeInformation& topic_info_, - QualityFlags description_quality_); - - bool ApplyServiceDescription(const std::string& service_name_, - const std::string& method_name_, - const SDataTypeInformation& request_type_information_, - const SDataTypeInformation& response_type_information_, - QualityFlags description_quality_); + void GetClients(std::map, SServiceMethodInformation>& client_info_map_); + void GetClientMethodNames(std::vector>& client_method_names_); + bool GetClientTypeNames(const std::string& client_name_, const std::string& method_name_, std::string& req_type_name_, std::string& resp_type_name_); + bool GetClientDescription(const std::string& client_name_, const std::string& method_name_, std::string& req_type_desc_, std::string& resp_type_desc_); + protected: struct STopicInfoQuality { SDataTypeInformation info; //!< Topic info struct with type encoding, name and descriptor. + std::string id; //!< Topic ID QualityFlags quality = QualityFlags::NO_QUALITY; //!< QualityFlags to determine whether we may overwrite the current data with better one. E.g. we prefer the description sent by a publisher over one sent by a subscriber. bool type_missmatch_logged = false; //!< Whether we have already logged a type-missmatch }; @@ -99,6 +93,7 @@ namespace eCAL struct SServiceMethodInfoQuality { SServiceMethodInformation info; //!< Service info struct with type names and descriptors for request and response. + std::string id; //!< Service ID QualityFlags quality = QualityFlags::NO_QUALITY; //!< The Quality of the Info }; @@ -127,6 +122,34 @@ namespace eCAL std::unique_ptr map; //!< Map containing information about each known service }; SServiceMethodInfoMap m_service_info_map; + SServiceMethodInfoMap m_client_info_map; + + bool ApplySample(const Registration::Sample& sample_, eTLayerType layer_); + + bool ApplyTopicDescription(const std::string& topic_name_, + const std::string& topic_id_, + const SDataTypeInformation& topic_info_, + QualityFlags description_quality_); + + bool RemTopicDescription(const std::string& topic_name_, + const std::string& topic_id_); + + bool ApplyServiceDescription(SServiceMethodInfoMap& service_method_map_, + const std::string& service_name_, + const std::string& service_id_, + const std::string& method_name_, + const SDataTypeInformation& request_type_information_, + const SDataTypeInformation& response_type_information_, + QualityFlags description_quality_); + + bool RemServiceDescription(SServiceMethodInfoMap& service_method_map_, + const std::string& service_name_, + const std::string& service_id_); + + void GetServices(std::map, SServiceMethodInformation>& service_info_map_, const SServiceMethodInfoMap& service_method_map_); + void GetServiceMethodNames(std::vector>& method_names_, const SServiceMethodInfoMap& service_method_map_); + bool GetServiceTypeNames(const std::string& service_name_, const std::string& method_name_, std::string& req_type_name_, std::string& resp_type_name_, const SServiceMethodInfoMap& service_method_map_); + bool GetServiceDescription(const std::string& service_name_, const std::string& method_name_, std::string& req_type_desc_, std::string& resp_type_desc_, const SServiceMethodInfoMap& service_method_map_); }; constexpr inline CDescGate::QualityFlags operator~ (CDescGate::QualityFlags a) { return static_cast( ~static_cast::type>(a) ); } diff --git a/ecal/core/src/ecal_util.cpp b/ecal/core/src/ecal_util.cpp index b0362b19ab..ad7470b57e 100644 --- a/ecal/core/src/ecal_util.cpp +++ b/ecal/core/src/ecal_util.cpp @@ -192,10 +192,10 @@ namespace eCAL g_descgate()->GetServices(service_info_map_); } - void GetServiceNames(std::vector>& service_method_names_) + void GetServiceMethodNames(std::vector>& service_method_names_) { if (g_descgate() == nullptr) return; - g_descgate()->GetServiceNames(service_method_names_); + g_descgate()->GetServiceMethodNames(service_method_names_); } bool GetServiceTypeNames(const std::string& service_name_, const std::string& method_name_, std::string& req_type_, std::string& resp_type_) @@ -210,6 +210,30 @@ namespace eCAL return(g_descgate()->GetServiceDescription(service_name_, method_name_, req_desc_, resp_desc_)); } + void GetClients(std::map, SServiceMethodInformation>& client_info_map_) + { + if (g_descgate() == nullptr) return; + g_descgate()->GetClients(client_info_map_); + } + + void GetClientMethodNames(std::vector>& client_method_names_) + { + if (g_descgate() == nullptr) return; + g_descgate()->GetClientMethodNames(client_method_names_); + } + + bool GetClientTypeNames(const std::string& client_name_, const std::string& method_name_, std::string& req_type_, std::string& resp_type_) + { + if (g_descgate() == nullptr) return(false); + return(g_descgate()->GetClientTypeNames(client_name_, method_name_, req_type_, resp_type_)); + } + + bool GetClientDescription(const std::string& client_name_, const std::string& method_name_, std::string& req_desc_, std::string& resp_desc_) + { + if (g_descgate() == nullptr) return(false); + return(g_descgate()->GetClientDescription(client_name_, method_name_, req_desc_, resp_desc_)); + } + std::pair SplitCombinedTopicType(const std::string& combined_topic_type_) { auto pos = combined_topic_type_.find(':'); diff --git a/ecal/samples/cpp/monitoring/monitoring_get_services/src/monitoring_get_services.cpp b/ecal/samples/cpp/monitoring/monitoring_get_services/src/monitoring_get_services.cpp index 6ebe66fd30..bdffe6bc46 100644 --- a/ecal/samples/cpp/monitoring/monitoring_get_services/src/monitoring_get_services.cpp +++ b/ecal/samples/cpp/monitoring/monitoring_get_services/src/monitoring_get_services.cpp @@ -52,14 +52,14 @@ int main(int argc, char **argv) std::cout << std::endl; } - // GetServiceNames + // GetServiceMethodNames { std::vector> service_method_names; start_time = std::chrono::steady_clock::now(); for (run = 0; run < runs; ++run) { - eCAL::Util::GetServiceNames(service_method_names); + eCAL::Util::GetServiceMethodNames(service_method_names); } auto num_services = service_method_names.size(); diff --git a/ecal/tests/cpp/clientserver_test/CMakeLists.txt b/ecal/tests/cpp/clientserver_test/CMakeLists.txt index 5c9877d9af..53557154da 100644 --- a/ecal/tests/cpp/clientserver_test/CMakeLists.txt +++ b/ecal/tests/cpp/clientserver_test/CMakeLists.txt @@ -25,7 +25,6 @@ create_targets_protobuf() set(${PROJECT_NAME}_src src/atomic_signalable.h - src/clientserver_getservices.cpp src/clientserver_test.cpp ) diff --git a/ecal/tests/cpp/pubsub_test/CMakeLists.txt b/ecal/tests/cpp/pubsub_test/CMakeLists.txt index 3243b3daad..5a9e74effd 100644 --- a/ecal/tests/cpp/pubsub_test/CMakeLists.txt +++ b/ecal/tests/cpp/pubsub_test/CMakeLists.txt @@ -23,7 +23,6 @@ find_package(GTest REQUIRED) set(pubsub_test_src src/pubsub_acknowledge.cpp - src/pubsub_gettopics.cpp src/pubsub_multibuffer.cpp src/pubsub_receive_test.cpp src/pubsub_test.cpp diff --git a/ecal/tests/cpp/util_test/CMakeLists.txt b/ecal/tests/cpp/util_test/CMakeLists.txt index d46da381f5..0baf7de422 100644 --- a/ecal/tests/cpp/util_test/CMakeLists.txt +++ b/ecal/tests/cpp/util_test/CMakeLists.txt @@ -21,7 +21,11 @@ project(test_util) find_package(Threads REQUIRED) find_package(GTest REQUIRED) + set(util_test_src + src/util_getclients.cpp + src/util_getservices.cpp + src/util_gettopics.cpp src/util_test.cpp ) diff --git a/ecal/tests/cpp/util_test/src/util_getclients.cpp b/ecal/tests/cpp/util_test/src/util_getclients.cpp new file mode 100644 index 0000000000..7b5230a56d --- /dev/null +++ b/ecal/tests/cpp/util_test/src/util_getclients.cpp @@ -0,0 +1,160 @@ +/* ========================= eCAL LICENSE ================================= + * + * Copyright (C) 2016 - 2019 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 ================================= +*/ + +#include +#include + +#include + +#define CMN_REGISTRATION_REFRESH 1000 +#define CMN_MONITORING_TIMEOUT 5000 + +TEST(core_cpp_util, GetClients) +{ + // initialize eCAL API + eCAL::Initialize(0, nullptr, "util_getclients"); + + std::map, eCAL::SServiceMethodInformation> client_info_map; + + // add and expire simple client + { + // create client + eCAL::SServiceMethodInformation service_method_info; + service_method_info.request_type.name = "foo::req_type1"; + service_method_info.request_type.descriptor = "foo::req_desc1"; + service_method_info.response_type.name = "foo::resp_type1"; + service_method_info.response_type.descriptor = "foo::resp_desc1"; + eCAL::CServiceClient client("foo::service", { {"foo::method", service_method_info} }); + + // get all clients + eCAL::Util::GetClients(client_info_map); + + // check size + EXPECT_EQ(client_info_map.size(), 1); + + // let's wait a monitoring timeout long + eCAL::Process::SleepMS(CMN_MONITORING_TIMEOUT); + + // get all clients again, client should not be expired + eCAL::Util::GetClients(client_info_map); + + // check size + EXPECT_EQ(client_info_map.size(), 1); + } + + // get all clients again, all clients + // should be removed from the map + eCAL::Util::GetClients(client_info_map); + + // check size + EXPECT_EQ(client_info_map.size(), 0); + + // create 2 clients + { + // create client 1 + eCAL::SServiceMethodInformation service_method_info1; + service_method_info1.request_type.name = "foo::req_type1"; + service_method_info1.request_type.descriptor = "foo::req_desc1"; + service_method_info1.response_type.name = "foo::resp_type1"; + service_method_info1.response_type.descriptor = "foo::resp_desc1"; + eCAL::CServiceClient client1("foo::service", { {"foo::method", service_method_info1} }); + + // get all clients + eCAL::Util::GetClients(client_info_map); + + // check size + EXPECT_EQ(client_info_map.size(), 1); + + // check attributes + std::string req_type, resp_type; + std::string req_desc, resp_desc; + + eCAL::Util::GetClientTypeNames("foo::service", "foo::method", req_type, resp_type); + EXPECT_EQ(req_type, "foo::req_type1"); + EXPECT_EQ(resp_type, "foo::resp_type1"); + eCAL::Util::GetClientDescription("foo::service", "foo::method", req_desc, resp_desc); + EXPECT_EQ(req_desc, "foo::req_desc1"); + EXPECT_EQ(resp_desc, "foo::resp_desc1"); + + // check client/method names + std::vector> client_method_names; + eCAL::Util::GetClientMethodNames(client_method_names); + EXPECT_EQ(client_method_names.size(), 1); + for (const auto& method_name : client_method_names) + { + EXPECT_EQ(std::get<0>(method_name), "foo::service"); + EXPECT_EQ(std::get<1>(method_name), "foo::method"); + } + + // create client 2 + // this will not overwrite the attributes from client1 + eCAL::SServiceMethodInformation service_method_info2; + service_method_info2.request_type.name = "foo::req_type2"; + service_method_info2.request_type.descriptor = "foo::req_desc2"; + service_method_info2.response_type.name = "foo::resp_type2"; + service_method_info2.response_type.descriptor = "foo::resp_desc2"; + eCAL::CServiceClient client2("foo::service", { {"foo::method", service_method_info2} }); + + // check attributes + eCAL::Util::GetClientTypeNames("foo::service", "foo::method", req_type, resp_type); + EXPECT_EQ(req_type, "foo::req_type1"); + EXPECT_EQ(resp_type, "foo::resp_type1"); + eCAL::Util::GetClientDescription("foo::service", "foo::method", req_desc, resp_desc); + EXPECT_EQ(req_desc, "foo::req_desc1"); + EXPECT_EQ(resp_desc, "foo::resp_desc1"); + + // check size (client1 replaced by client2) + EXPECT_EQ(client_info_map.size(), 1); + + // let's wait a monitoring timeout long + eCAL::Process::SleepMS(CMN_MONITORING_TIMEOUT); + + // get all clients again, client should not be expired + eCAL::Util::GetClients(client_info_map); + + // check size + EXPECT_EQ(client_info_map.size(), 1); + + // destroy client 1 + client1.Destroy(); + + // check attributes (client 1 is still in the map) + eCAL::Util::GetClientTypeNames("foo::service", "foo::method", req_type, resp_type); + EXPECT_EQ(req_type, "foo::req_type1"); + EXPECT_EQ(resp_type, "foo::resp_type1"); + + // let's wait a registration cylce long + eCAL::Process::SleepMS(CMN_REGISTRATION_REFRESH); + + // check attributes (client 1 should be replaced by client 2 now) + eCAL::Util::GetClientTypeNames("foo::service", "foo::method", req_type, resp_type); + EXPECT_EQ(req_type, "foo::req_type2"); + EXPECT_EQ(resp_type, "foo::resp_type2"); + } + + // get all clients again, all clients + // should be removed from the map + eCAL::Util::GetClients(client_info_map); + + // check size + EXPECT_EQ(client_info_map.size(), 0); + + // finalize eCAL API + eCAL::Finalize(); +} diff --git a/ecal/tests/cpp/clientserver_test/src/clientserver_getservices.cpp b/ecal/tests/cpp/util_test/src/util_getservices.cpp similarity index 92% rename from ecal/tests/cpp/clientserver_test/src/clientserver_getservices.cpp rename to ecal/tests/cpp/util_test/src/util_getservices.cpp index a4c9f445c2..0a6837785d 100644 --- a/ecal/tests/cpp/clientserver_test/src/clientserver_getservices.cpp +++ b/ecal/tests/cpp/util_test/src/util_getservices.cpp @@ -24,10 +24,10 @@ #define CMN_MONITORING_TIMEOUT 5000 -TEST(core_cpp_clientserver, GetServices) +TEST(core_cpp_util, GetServices) { // initialize eCAL API - eCAL::Initialize(0, nullptr, "clientserver_getservices"); + eCAL::Initialize(0, nullptr, "util_getservices"); std::map, eCAL::SServiceMethodInformation> service_info_map; @@ -54,10 +54,8 @@ TEST(core_cpp_clientserver, GetServices) // check size EXPECT_EQ(service_info_map.size(), 1); } - // let's unregister them - eCAL::Process::SleepMS(CMN_MONITORING_TIMEOUT + 1000); - // get all services again, now all services + // get all services again, all services // should be removed from the map eCAL::Util::GetServices(service_info_map); @@ -125,10 +123,8 @@ TEST(core_cpp_clientserver, GetServices) // check size EXPECT_EQ(service_info_map.size(), 1); } - // let's unregister them - eCAL::Process::SleepMS(CMN_MONITORING_TIMEOUT + 1000); - // get all services again, now all services + // get all services again, all services // should be removed from the map eCAL::Util::GetServices(service_info_map); diff --git a/ecal/tests/cpp/pubsub_test/src/pubsub_gettopics.cpp b/ecal/tests/cpp/util_test/src/util_gettopics.cpp similarity index 61% rename from ecal/tests/cpp/pubsub_test/src/pubsub_gettopics.cpp rename to ecal/tests/cpp/util_test/src/util_gettopics.cpp index 66e4dc6eaa..bb50a2ab7d 100644 --- a/ecal/tests/cpp/pubsub_test/src/pubsub_gettopics.cpp +++ b/ecal/tests/cpp/util_test/src/util_gettopics.cpp @@ -20,13 +20,15 @@ #include #include +#include +#include #include -#define CMN_REGISTRATION_REFRESH 1000 -#define CMN_MONITORING_TIMEOUT 5000 +#define CMN_REGISTRATION_REFRESH 1000 +#define CMN_MONITORING_TIMEOUT 5000 -TEST(core_cpp_pubsub, GetTopics) +TEST(core_cpp_util, GetTopics) { // initialize eCAL API eCAL::Initialize(0, nullptr, "pubsub_gettopics"); @@ -91,20 +93,15 @@ TEST(core_cpp_pubsub, GetTopics) pub1.Destroy(); sub1.Destroy(); - // pub1 and sub1 still exists { eCAL::SDataTypeInformation utils_topic_info; eCAL::Util::GetTopicDataTypeInformation("A1", utils_topic_info); - EXPECT_EQ(utils_topic_info, info_A1); - } - { - eCAL::SDataTypeInformation utils_topic_info; - eCAL::Util::GetTopicDataTypeInformation("B1", utils_topic_info); - EXPECT_EQ(utils_topic_info, info_B1); + EXPECT_EQ(false, eCAL::Util::GetTopicDataTypeInformation("A1", utils_topic_info)); + EXPECT_EQ(false, eCAL::Util::GetTopicDataTypeInformation("B1", utils_topic_info)); } - // wait a monitoring timeout long, and let pub1.2 and sub1.2 register - eCAL::Process::SleepMS(CMN_MONITORING_TIMEOUT + CMN_REGISTRATION_REFRESH); + // 2 registration cycles + eCAL::Process::SleepMS(2 * CMN_REGISTRATION_REFRESH); // update map eCAL::Util::GetTopics(topic_info_map); @@ -138,3 +135,69 @@ TEST(core_cpp_pubsub, GetTopics) // finalize eCAL API eCAL::Finalize(); } + +TEST(core_cpp_util, GetTopicsParallel) +{ + constexpr const int max_publisher_count(2000); + constexpr const int waiting_time_thread(1000); + constexpr const int parallel_threads(1); + + eCAL::Initialize(); + + auto create_publishers = [&]() { + std::string topic_name = "Test.ParallelUtilFunctions"; + std::atomic call_back_count{ 0 }; + + std::vector> publishers; + for (int pub_count = 0; pub_count < max_publisher_count; pub_count++) { + std::unique_ptr publisher = std::make_unique(topic_name + std::to_string(pub_count)); + publishers.push_back(std::move(publisher)); + } + std::this_thread::sleep_for(std::chrono::milliseconds(waiting_time_thread)); + }; + + auto get_topics_from_ecal = [&]() { + size_t found_topics = 0; + std::vector tmp_topic_names; + std::unordered_map topics; + do { + eCAL::Util::GetTopicNames(tmp_topic_names); + eCAL::Util::GetTopics(topics); + + found_topics = tmp_topic_names.size(); + std::cout << "Number of topics found by ecal: " << found_topics << "\n"; + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + } while (found_topics < max_publisher_count); + + // do it again until all publishers are deleted + do { + eCAL::Util::GetTopicNames(tmp_topic_names); + eCAL::Util::GetTopics(topics); + + found_topics = tmp_topic_names.size(); + std::cout << "Number of topics found by ecal: " << found_topics << "\n"; + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + } while (found_topics != 0); + }; + + std::vector threads_container; + threads_container.push_back(std::thread(create_publishers)); + + for (size_t i = 0; i < parallel_threads; i++) { + threads_container.push_back(std::thread(get_topics_from_ecal)); + } + + for (auto& th : threads_container) { + th.join(); + } + + std::vector final_topic_names; + std::unordered_map final_topics; + eCAL::Util::GetTopicNames(final_topic_names); + eCAL::Util::GetTopics(final_topics); + + EXPECT_EQ(final_topic_names.size(), 0); + EXPECT_EQ(final_topics.size(), 0); + + eCAL::Finalize(); +} diff --git a/ecal/tests/cpp/util_test/src/util_test.cpp b/ecal/tests/cpp/util_test/src/util_test.cpp index d7aa7f8fe5..d631066fb1 100644 --- a/ecal/tests/cpp/util_test/src/util_test.cpp +++ b/ecal/tests/cpp/util_test/src/util_test.cpp @@ -21,7 +21,6 @@ #include #include -#include #include @@ -194,69 +193,3 @@ TEST(core_cpp_util, Freq_ResettableFrequencyCalculator) } } } - -TEST(core_cpp_util, ParallelGetTopics) -{ - constexpr const int max_publisher_count(2000); - constexpr const int waiting_time_thread(1000); - constexpr const int parallel_threads(1); - - eCAL::Initialize(); - - auto create_publishers = [&]() { - std::string topic_name = "Test.ParallelUtilFunctions"; - std::atomic call_back_count{ 0 }; - - std::vector> publishers; - for (int pub_count = 0; pub_count < max_publisher_count; pub_count++) { - std::unique_ptr publisher = std::make_unique(topic_name + std::to_string(pub_count)); - publishers.push_back(std::move(publisher)); - } - std::this_thread::sleep_for(std::chrono::milliseconds(waiting_time_thread)); - }; - - auto get_topics_from_ecal = [&]() { - size_t found_topics = 0; - std::vector tmp_topic_names; - std::unordered_map topics; - do { - eCAL::Util::GetTopicNames(tmp_topic_names); - eCAL::Util::GetTopics(topics); - - found_topics = tmp_topic_names.size(); - std::cout << "Number of topics found by ecal: " << found_topics << "\n"; - std::this_thread::sleep_for(std::chrono::milliseconds(500)); - } while (found_topics < max_publisher_count); - - // do it again until all publishers are deleted - do { - eCAL::Util::GetTopicNames(tmp_topic_names); - eCAL::Util::GetTopics(topics); - - found_topics = tmp_topic_names.size(); - std::cout << "Number of topics found by ecal: " << found_topics << "\n"; - std::this_thread::sleep_for(std::chrono::milliseconds(500)); - } while (found_topics != 0); - }; - - std::vector threads_container; - threads_container.push_back(std::thread(create_publishers)); - - for (size_t i = 0; i < parallel_threads; i++) { - threads_container.push_back(std::thread(get_topics_from_ecal)); - } - - for (auto& th : threads_container) { - th.join(); - } - - std::vector final_topic_names; - std::unordered_map final_topics; - eCAL::Util::GetTopicNames(final_topic_names); - eCAL::Util::GetTopics(final_topics); - - EXPECT_EQ(final_topic_names.size(), 0); - EXPECT_EQ(final_topics.size(), 0); - - eCAL::Finalize(); -} From 5b8c21be1b9726884f542ce32da2e7ef079d74fe Mon Sep 17 00:00:00 2001 From: rex-schilasky <49162693+rex-schilasky@users.noreply.github.com> Date: Wed, 10 Apr 2024 13:23:24 +0200 Subject: [PATCH 02/27] minor logic bug --- ecal/core/src/ecal_descgate.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ecal/core/src/ecal_descgate.cpp b/ecal/core/src/ecal_descgate.cpp index 08878df508..d1754394c2 100644 --- a/ecal/core/src/ecal_descgate.cpp +++ b/ecal/core/src/ecal_descgate.cpp @@ -459,10 +459,10 @@ namespace eCAL } // the entry is existing, the requested quality is not higher - // update the existing entry if it has the same attributes (independing from the unique id) + // update the timestamp of the existing entry if (service_info.info == req_service_info.info) { - (*service_method_map_.map)[service_method_tuple] = req_service_info; + (*service_method_map_.map)[service_method_tuple] = service_info; return true; } From a68af976820e12db4c335a2c1f15a7bfb0310b03 Mon Sep 17 00:00:00 2001 From: rex-schilasky <49162693+rex-schilasky@users.noreply.github.com> Date: Wed, 10 Apr 2024 15:27:29 +0200 Subject: [PATCH 03/27] expmap test moved to core (solution folder) --- ecal/tests/cpp/expmap_test/src/expmap_test.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/ecal/tests/cpp/expmap_test/src/expmap_test.cpp b/ecal/tests/cpp/expmap_test/src/expmap_test.cpp index 8db191f0e2..224eae6afd 100644 --- a/ecal/tests/cpp/expmap_test/src/expmap_test.cpp +++ b/ecal/tests/cpp/expmap_test/src/expmap_test.cpp @@ -27,7 +27,7 @@ #include -TEST(core_cpp_util, ExpMap_SetGet) +TEST(core_cpp_core, ExpMap_SetGet) { // create the map with 2500 ms expiration eCAL::Util::CExpMap expmap(std::chrono::milliseconds(200)); @@ -86,7 +86,7 @@ TEST(core_cpp_util, ExpMap_SetGet) std::this_thread::sleep_for(std::chrono::milliseconds(150)); } -TEST(core_cpp_util, ExpMap_Insert) +TEST(core_cpp_core, ExpMap_Insert) { eCAL::Util::CExpMap expmap(std::chrono::milliseconds(200)); auto ret = expmap.insert(std::make_pair("A", 1)); @@ -106,7 +106,7 @@ TEST(core_cpp_util, ExpMap_Insert) } // This tests uses find to find an element -TEST(core_cpp_util, ExpMap_Find) +TEST(core_cpp_core, ExpMap_Find) { eCAL::Util::CExpMap expmap(std::chrono::milliseconds(200)); @@ -125,7 +125,7 @@ TEST(core_cpp_util, ExpMap_Find) } // This test assures that find can be called on a const CExpMap and returns an CExpMap::const_iterator -TEST(core_cpp_util, ExpMap_FindConst) +TEST(core_cpp_core, ExpMap_FindConst) { eCAL::Util::CExpMap expmap(std::chrono::milliseconds(200)); @@ -146,7 +146,7 @@ TEST(core_cpp_util, ExpMap_FindConst) EXPECT_EQ(0, expmap.size()); } -TEST(core_cpp_util, ExpMap_Iterate) +TEST(core_cpp_core, ExpMap_Iterate) { // create the map with 2500 ms expiration eCAL::Util::CExpMap expmap(std::chrono::milliseconds(200)); @@ -180,7 +180,7 @@ void ConstRefIterate(const eCAL::Util::CExpMap& map) EXPECT_EQ(1, value); } -TEST(core_cpp_util, ExpMap_ConstExpMapIterate) +TEST(core_cpp_core, ExpMap_ConstExpMapIterate) { // create the map with 2500 ms expiration eCAL::Util::CExpMap expmap(std::chrono::milliseconds(200)); @@ -189,7 +189,7 @@ TEST(core_cpp_util, ExpMap_ConstExpMapIterate) ConstRefIterate(expmap); } -TEST(core_cpp_util, ExpMap_Empty) +TEST(core_cpp_core, ExpMap_Empty) { eCAL::Util::CExpMap expmap(std::chrono::milliseconds(200)); EXPECT_EQ(true, expmap.empty()); @@ -197,7 +197,7 @@ TEST(core_cpp_util, ExpMap_Empty) EXPECT_EQ(false, expmap.empty()); } -TEST(core_cpp_util, ExpMap_Size) +TEST(core_cpp_core, ExpMap_Size) { eCAL::Util::CExpMap expmap(std::chrono::milliseconds(200)); EXPECT_EQ(0, expmap.size()); @@ -205,7 +205,7 @@ TEST(core_cpp_util, ExpMap_Size) EXPECT_EQ(1, expmap.size()); } -TEST(core_cpp_util, ExpMap_Remove) +TEST(core_cpp_core, ExpMap_Remove) { eCAL::Util::CExpMap expmap(std::chrono::milliseconds(200)); expmap["A"] = 1; From e3f0afdb6b15c6e2a5276fa5a9626d54ba65df59 Mon Sep 17 00:00:00 2001 From: rex-schilasky <49162693+rex-schilasky@users.noreply.github.com> Date: Fri, 12 Apr 2024 15:52:30 +0200 Subject: [PATCH 04/27] descgate first draft finished ecal_util started to adapt --- ecal/core/include/ecal/ecal_util.h | 111 ++++++- ecal/core/src/ecal_descgate.cpp | 475 ++++++----------------------- ecal/core/src/ecal_descgate.h | 134 ++++---- ecal/core/src/ecal_util.cpp | 290 ++++++++++++++++-- 4 files changed, 528 insertions(+), 482 deletions(-) diff --git a/ecal/core/include/ecal/ecal_util.h b/ecal/core/include/ecal/ecal_util.h index 9a258d4587..1d8b7143ed 100644 --- a/ecal/core/include/ecal/ecal_util.h +++ b/ecal/core/include/ecal/ecal_util.h @@ -27,8 +27,8 @@ #include #include #include - #include +#include #include #include #include @@ -37,8 +37,33 @@ namespace eCAL { - namespace Util - { + namespace Util + { + // enumeration of quality bits used for detecting how good a data information is + enum class DescQualityFlags : int + { + NO_QUALITY = 0, //!< Special value for initialization + DESCRIPTION_AVAILABLE = 0x1 << 3, //!< Having a type descriptor available + ENCODING_AVAILABLE = 0x1 << 2, //!< Having a type encoding + TYPENAME_AVAILABLE = 0x1 << 1, //!< Having a type name available + INFO_COMES_FROM_PRODUCER = 0x1 << 0 //!< Info is coming from the producer (like a publisher, service) + }; + inline DescQualityFlags& operator|= (DescQualityFlags& a, DescQualityFlags b) { return reinterpret_cast(reinterpret_cast::type&>(a) |= static_cast::type>(b)); } + + struct SQualityDataTypeInformation + { + std::string id; + SDataTypeInformation info; + DescQualityFlags quality = DescQualityFlags::NO_QUALITY; + }; + + struct SQualityServiceMethodInformation + { + std::string id; + SServiceMethodInformation info; + DescQualityFlags quality = DescQualityFlags::NO_QUALITY; + }; + /** * @brief Retrieve eCAL configuration path. * This is path is for the global eCAL configuration files @@ -124,12 +149,82 @@ namespace eCAL ECAL_API void PubShareDescription(bool state_); /** - * @brief Get complete topic map (including types and descriptions). + * @brief Get complete snapshot of data type information with quality and topic id for all known publisher. + * + * @return MultiMap containing the qualified datatype information and the topic id's. + **/ + ECAL_API std::multimap GetPublisher(); + + /** + * @brief Get data type information with quality and topic id for this publisher. + * + * @param topic_name_ Topic name. + * + * @return Vector containing the qualified datatype information for this publisher. + **/ + ECAL_API std::vector GetPublisher(const std::string& topic_name_); + + /** + * @brief Get complete snapshot of data type information with quality and topic id for all known subscriber. + * + * @return MultiMap containing the qualified datatype information and the topic id's. + **/ + ECAL_API std::multimap GetSubscriber(); + + /** + * @brief Get data type information with quality and topic id for this subscriber. + * + * @param topic_name_ Topic name. + * + * @return Vector containing the qualified datatype information for this subscriber. + **/ + ECAL_API std::vector GetSubscriber(const std::string& topic_name_); + + /** + * @brief Get highest qualified data type information out of a vector of qualified data type information. + * + * @param data_type_info_vec_ Vector of qualified data type information + * + * @return Highest qualified data type information. + **/ + ECAL_API SDataTypeInformation GetHighestQualifiedDataTypeInformation(const std::vector& data_type_info_vec_); + + /** + * @brief Get complete snapshot of service method information with quality and service id for all known services. + * + * @return MultiMap containing the qualified datatype information and the service id's. + **/ + ECAL_API std::multimap, SQualityServiceMethodInformation> GetServices(); + + /** + * @brief Get complete snapshot of service method information with quality and client id for all known clients. + * + * @return MultiMap containing the qualified datatype information and the client id's. + **/ + ECAL_API std::multimap, SQualityServiceMethodInformation> GetClients(); + + /** + * @brief Get highest qualified service method type information out of a vector of qualified service method information. + * + * @param service_method_info_vec_ Vector of qualified service method information + * + * @return Highest qualified service method information. + **/ + ECAL_API SServiceMethodInformation GetHighestQualifiedServiceMethodInformation(const std::vector& service_method_info_vec_); + + /** + * @brief Get complete topic map. + * + * @param topic_info_map_ Map to store the datatype information. + **/ + ECAL_API void GetTopics(std::unordered_map& data_type_info_map_); + + /** + * @brief Get complete qualified topic map. * - * @param topic_info_map_ Map to store the datatype descriptions. - * Map containing { TopicName -> (Encoding, Type, Description) } mapping of all topics that are currently known. + * @param topic_info_map_ Map to store the qualified datatype information. **/ - ECAL_API void GetTopics(std::unordered_map& topic_info_map_); + ECAL_API void GetTopics(std::unordered_map& qualfied_data_type_info_map_); /** * @brief Get all topic names. @@ -152,7 +247,7 @@ namespace eCAL * @brief Get complete service map (including request and response types and descriptions). * * @param service_info_map_ Map to store the datatype descriptions. - * Map { (ServiceName, MethodName) -> ( (ReqType, ReqDescription), (RespType, RespDescription) ) } mapping of all currently known services. + * Map { (ServiceName, MethodName) -> SServiceMethodInformation } mapping of all currently known services. **/ ECAL_API void GetServices(std::map, SServiceMethodInformation>& service_info_map_); diff --git a/ecal/core/src/ecal_descgate.cpp b/ecal/core/src/ecal_descgate.cpp index d1754394c2..d6b40d3c13 100644 --- a/ecal/core/src/ecal_descgate.cpp +++ b/ecal/core/src/ecal_descgate.cpp @@ -27,59 +27,43 @@ #include "ecal_globals.h" #include "ecal_descgate.h" -#include - namespace { - // TODO: remove me with new CDescGate - eCAL::CDescGate::QualityFlags GetServiceMethodQuality(const eCAL::SDataTypeInformation& request_info_, const eCAL::SDataTypeInformation& response_info_) + eCAL::Util::DescQualityFlags GetClientQuality(const eCAL::SDataTypeInformation& request_info_, const eCAL::SDataTypeInformation& response_info_) { - eCAL::CDescGate::QualityFlags quality = eCAL::CDescGate::QualityFlags::NO_QUALITY; + eCAL::Util::DescQualityFlags quality = eCAL::Util::DescQualityFlags::NO_QUALITY; if (!(request_info_.name.empty() && response_info_.name.empty())) - quality |= eCAL::CDescGate::QualityFlags::TYPE_AVAILABLE; + quality |= eCAL::Util::DescQualityFlags::TYPENAME_AVAILABLE; + if (!(request_info_.encoding.empty() && response_info_.encoding.empty())) + quality |= eCAL::Util::DescQualityFlags::ENCODING_AVAILABLE; if (!(request_info_.descriptor.empty() && response_info_.descriptor.empty())) - quality |= eCAL::CDescGate::QualityFlags::DESCRIPTION_AVAILABLE; - quality |= eCAL::CDescGate::QualityFlags::INFO_COMES_FROM_PRODUCER; - + quality |= eCAL::Util::DescQualityFlags::DESCRIPTION_AVAILABLE; return quality; } - // TODO: remove me with new CDescGate - eCAL::CDescGate::QualityFlags GetClientMethodQuality(const eCAL::SDataTypeInformation& request_info_, const eCAL::SDataTypeInformation& response_info_) + eCAL::Util::DescQualityFlags GetServiceQuality(const eCAL::SDataTypeInformation& request_info_, const eCAL::SDataTypeInformation& response_info_) { - eCAL::CDescGate::QualityFlags quality = eCAL::CDescGate::QualityFlags::NO_QUALITY; - if (!(request_info_.name.empty() && response_info_.name.empty())) - quality |= eCAL::CDescGate::QualityFlags::TYPE_AVAILABLE; - if (!(request_info_.descriptor.empty() && response_info_.descriptor.empty())) - quality |= eCAL::CDescGate::QualityFlags::DESCRIPTION_AVAILABLE; - + eCAL::Util::DescQualityFlags quality = GetClientQuality(request_info_, response_info_); + quality |= eCAL::Util::DescQualityFlags::INFO_COMES_FROM_PRODUCER; return quality; } - // TODO: remove me with new CDescGate - eCAL::CDescGate::QualityFlags GetPublisherQuality(const eCAL::SDataTypeInformation& topic_info_) + eCAL::Util::DescQualityFlags GetSubscriberQuality(const eCAL::SDataTypeInformation& topic_info_) { - eCAL::CDescGate::QualityFlags quality = eCAL::CDescGate::QualityFlags::NO_QUALITY; - if (!topic_info_.name.empty() || !topic_info_.encoding.empty()) - quality |= eCAL::CDescGate::QualityFlags::TYPE_AVAILABLE; + eCAL::Util::DescQualityFlags quality = eCAL::Util::DescQualityFlags::NO_QUALITY; + if (!topic_info_.name.empty()) + quality |= eCAL::Util::DescQualityFlags::TYPENAME_AVAILABLE; + if (!topic_info_.encoding.empty()) + quality |= eCAL::Util::DescQualityFlags::ENCODING_AVAILABLE; if (!topic_info_.descriptor.empty()) - quality |= eCAL::CDescGate::QualityFlags::DESCRIPTION_AVAILABLE; - quality |= eCAL::CDescGate::QualityFlags::INFO_COMES_FROM_CORRECT_ENTITY; - quality |= eCAL::CDescGate::QualityFlags::INFO_COMES_FROM_PRODUCER; - + quality |= eCAL::Util::DescQualityFlags::DESCRIPTION_AVAILABLE; return quality; } - // TODO: remove me with new CDescGate - eCAL::CDescGate::QualityFlags GetSubscriberQuality(const eCAL::SDataTypeInformation& topic_info_) + eCAL::Util::DescQualityFlags GetPublisherQuality(const eCAL::SDataTypeInformation& topic_info_) { - eCAL::CDescGate::QualityFlags quality = eCAL::CDescGate::QualityFlags::NO_QUALITY; - if (!topic_info_.name.empty() || !topic_info_.encoding.empty()) - quality |= eCAL::CDescGate::QualityFlags::TYPE_AVAILABLE; - if (!topic_info_.descriptor.empty()) - quality |= eCAL::CDescGate::QualityFlags::DESCRIPTION_AVAILABLE; - quality |= eCAL::CDescGate::QualityFlags::INFO_COMES_FROM_CORRECT_ENTITY; - + eCAL::Util::DescQualityFlags quality = GetSubscriberQuality(topic_info_); + quality |= eCAL::Util::DescQualityFlags::INFO_COMES_FROM_PRODUCER; return quality; } } @@ -87,9 +71,10 @@ namespace namespace eCAL { CDescGate::CDescGate() : - m_topic_info_map(std::chrono::milliseconds(Config::GetMonitoringTimeoutMs())), - m_service_info_map(std::chrono::milliseconds(Config::GetMonitoringTimeoutMs())), - m_client_info_map(std::chrono::milliseconds(Config::GetMonitoringTimeoutMs())) + m_publisher_info_map (std::chrono::milliseconds(Config::GetMonitoringTimeoutMs())), + m_subscriber_info_map (std::chrono::milliseconds(Config::GetMonitoringTimeoutMs())), + m_service_info_map (std::chrono::milliseconds(Config::GetMonitoringTimeoutMs())), + m_client_info_map (std::chrono::milliseconds(Config::GetMonitoringTimeoutMs())) { } CDescGate::~CDescGate() = default; @@ -112,89 +97,55 @@ namespace eCAL #endif } - void CDescGate::GetTopics(std::unordered_map& topic_info_map_) + CDescGate::TopicNameIdMap CDescGate::GetPublisher() { - std::unordered_map map; - - const std::lock_guard lock(m_topic_info_map.sync); - m_topic_info_map.map->remove_deprecated(); - map.reserve(m_topic_info_map.map->size()); - - for (const auto& topic_info : (*m_topic_info_map.map)) - { - map.emplace(topic_info.first, topic_info.second.info); - } - topic_info_map_.swap(map); + return GetTopics(m_publisher_info_map); } - void CDescGate::GetTopicNames(std::vector& topic_names_) + CDescGate::TopicNameIdMap CDescGate::GetSubscriber() { - topic_names_.clear(); - - const std::lock_guard lock(m_topic_info_map.sync); - m_topic_info_map.map->remove_deprecated(); - topic_names_.reserve(m_topic_info_map.map->size()); - - for (const auto& topic_info : (*m_topic_info_map.map)) - { - topic_names_.emplace_back(topic_info.first); - } - } - - bool CDescGate::GetDataTypeInformation(const std::string& topic_name_, SDataTypeInformation& topic_info_) - { - if (topic_name_.empty()) return(false); - - const std::lock_guard lock(m_topic_info_map.sync); - m_topic_info_map.map->remove_deprecated(); - const auto topic_info_it = m_topic_info_map.map->find(topic_name_); - - if (topic_info_it == m_topic_info_map.map->end()) return(false); - topic_info_ = (*topic_info_it).second.info; - return(true); + return GetTopics(m_subscriber_info_map); } - void CDescGate::GetServices(std::map, SServiceMethodInformation>& service_info_map_) + CDescGate::ServiceMethodNameIdMap CDescGate::GetServices() { - GetServices(service_info_map_, m_service_info_map); + return GetServices(m_service_info_map); } - void CDescGate::GetServiceMethodNames(std::vector>& service_method_names_) + CDescGate::ServiceMethodNameIdMap CDescGate::GetClients() { - GetServiceMethodNames(service_method_names_, m_service_info_map); + return GetServices(m_client_info_map); } - bool CDescGate::GetServiceTypeNames(const std::string& service_name_, const std::string& method_name_, std::string& req_type_name_, std::string& resp_type_name_) + CDescGate::TopicNameIdMap CDescGate::GetTopics(const STopicInfoMap& topic_map_) { - return GetServiceTypeNames(service_name_, method_name_, req_type_name_, resp_type_name_, m_service_info_map); - } + TopicNameIdMap map; - bool CDescGate::GetServiceDescription(const std::string& service_name_, const std::string& method_name_, std::string& req_type_desc_, std::string& resp_type_desc_) - { - return GetServiceDescription(service_name_, method_name_, req_type_desc_, resp_type_desc_, m_service_info_map); - } + const std::lock_guard lock(topic_map_.sync); + topic_map_.map->remove_deprecated(); - void CDescGate::GetClients(std::map, SServiceMethodInformation>& service_info_map_) - { - GetServices(service_info_map_, m_client_info_map); + for (const auto& topic_map_it : (*topic_map_.map)) + { + map.emplace(topic_map_it.first, topic_map_it.second); + } + return map; } - void CDescGate::GetClientMethodNames(std::vector>& client_method_names_) + CDescGate::ServiceMethodNameIdMap CDescGate::GetServices(const SServiceMethodInfoMap& service_method_info_map_) { - GetServiceMethodNames(client_method_names_, m_client_info_map); - } + ServiceMethodNameIdMap map; - bool CDescGate::GetClientTypeNames(const std::string& service_name_, const std::string& method_name_, std::string& req_type_name_, std::string& resp_type_name_) - { - return GetServiceTypeNames(service_name_, method_name_, req_type_name_, resp_type_name_, m_client_info_map); - } + const std::lock_guard lock(service_method_info_map_.sync); + service_method_info_map_.map->remove_deprecated(); - bool CDescGate::GetClientDescription(const std::string& service_name_, const std::string& method_name_, std::string& req_type_desc_, std::string& resp_type_desc_) - { - return GetServiceDescription(service_name_, method_name_, req_type_desc_, resp_type_desc_, m_client_info_map); + for (const auto& service_method_info_map_it : (*service_method_info_map_.map)) + { + map.emplace(service_method_info_map_it.first, service_method_info_map_it.second); + } + return map; } - bool CDescGate::ApplySample(const Registration::Sample& sample_, eTLayerType /*layer_*/) + void CDescGate::ApplySample(const Registration::Sample& sample_, eTLayerType /*layer_*/) { switch (sample_.cmd_type) { @@ -215,7 +166,7 @@ namespace eCAL response_type.name = method.resp_type; response_type.descriptor = method.resp_desc; - ApplyServiceDescription(m_service_info_map, sample_.service.sname, sample_.service.sid, method.mname, request_type, response_type, GetServiceMethodQuality(request_type, response_type)); + ApplyServiceDescription(m_service_info_map, sample_.service.sname, sample_.service.sid, method.mname, request_type, response_type, GetServiceQuality(request_type, response_type)); } } break; @@ -233,23 +184,23 @@ namespace eCAL response_type.name = method.resp_type; response_type.descriptor = method.resp_desc; - ApplyServiceDescription(m_client_info_map, sample_.client.sname, sample_.client.sid, method.mname, request_type, response_type, GetClientMethodQuality(request_type, response_type)); + ApplyServiceDescription(m_client_info_map, sample_.client.sname, sample_.client.sid, method.mname, request_type, response_type, GetClientQuality(request_type, response_type)); } break; case bct_unreg_client: RemServiceDescription(m_client_info_map, sample_.client.sname, sample_.client.sid); break; case bct_reg_publisher: - ApplyTopicDescription(sample_.topic.tname, sample_.topic.tid, sample_.topic.tdatatype, GetPublisherQuality(sample_.topic.tdatatype)); + ApplyTopicDescription(m_publisher_info_map, sample_.topic.tname, sample_.topic.tid, sample_.topic.tdatatype, GetPublisherQuality(sample_.topic.tdatatype)); break; case bct_unreg_publisher: - RemTopicDescription(sample_.topic.tname, sample_.topic.tid); + RemTopicDescription(m_publisher_info_map, sample_.topic.tname, sample_.topic.tid); break; case bct_reg_subscriber: - ApplyTopicDescription(sample_.topic.tname, sample_.topic.tid, sample_.topic.tdatatype, GetSubscriberQuality(sample_.topic.tdatatype)); + ApplyTopicDescription(m_subscriber_info_map, sample_.topic.tname, sample_.topic.tid, sample_.topic.tdatatype, GetSubscriberQuality(sample_.topic.tdatatype)); break; case bct_unreg_subscriber: - RemTopicDescription(sample_.topic.tname, sample_.topic.tid); + RemTopicDescription(m_subscriber_info_map, sample_.topic.tname, sample_.topic.tid); break; default: { @@ -257,301 +208,77 @@ namespace eCAL } break; } - - return true; } - bool CDescGate::ApplyTopicDescription(const std::string& topic_name_, const std::string& topic_id_, const SDataTypeInformation& topic_info_, const QualityFlags description_quality_) + void CDescGate::ApplyTopicDescription(STopicInfoMap& topic_info_map_, + const std::string& topic_name_, + const std::string& topic_id_, + const SDataTypeInformation& topic_info_, + Util::DescQualityFlags topic_quality_) { - const std::unique_lock lock(m_topic_info_map.sync); - m_topic_info_map.map->remove_deprecated(); - - const auto topic_info_it = m_topic_info_map.map->find(topic_name_); - - // new element (no need to check anything, just add it) - if (topic_info_it == m_topic_info_map.map->end()) - { - // create a new topic entry - STopicInfoQuality& topic_info = (*m_topic_info_map.map)[topic_name_]; - topic_info.id = topic_id_; - topic_info.info = topic_info_; - topic_info.quality = description_quality_; - return true; - } - - // we do not use the [] operator here to not update the timestamp - // by accessing the map entry - // - // a topic with the same name but different type name or different description - // should NOT update the timestamp of an existing entry - // - // otherwise there could be a scenario where a "lower quality topic" would keep a - // "higher quality topic" alive (even it is no more existing) - STopicInfoQuality topic_info = (*topic_info_it).second; - - // first let's check whether the current information has a higher quality - // if it has a higher quality, we overwrite it - if (description_quality_ > topic_info.quality) - { - // overwrite attributes - topic_info.id = topic_id_; - topic_info.info = topic_info_; - topic_info.quality = description_quality_; - - // update attributes and return - (*m_topic_info_map.map)[topic_name_] = topic_info; - return true; - } - - // this is the same topic (topic name, topic type name, topic type description) - // independing from the unique id - if (topic_info.info == topic_info_) - { - // update timestamp (by just accessing the entry) and return - (*m_topic_info_map.map)[topic_name_] = topic_info; - return false; - } + const auto topic_info_key = STopicNameId{ topic_name_, topic_id_ }; - // topic type name or topic description differ but we logged this before - if (topic_info.type_missmatch_logged) - { - return false; - } + Util::SQualityDataTypeInformation topic_quality_info; + topic_quality_info.id = topic_id_; + topic_quality_info.info = topic_info_; + topic_quality_info.quality = topic_quality_; - // topic type name or topic description differ and this is not logged yet - // so we log the error and update the entry one time - bool update_topic_info(false); + const std::unique_lock lock(topic_info_map_.sync); + topic_info_map_.map->remove_deprecated(); - // topic type name differs - // we log the error and update the entry one time - if (!topic_info_.encoding.empty() - && !topic_info.info.encoding.empty() - && (topic_info.info.encoding != topic_info_.encoding) - ) - { - std::string tencoding1 = topic_info.info.encoding; - std::string tencoding2 = topic_info_.encoding; - std::replace(tencoding1.begin(), tencoding1.end(), '\0', '?'); - std::replace(tencoding1.begin(), tencoding1.end(), '\t', '?'); - std::replace(tencoding2.begin(), tencoding2.end(), '\0', '?'); - std::replace(tencoding2.begin(), tencoding2.end(), '\t', '?'); - std::string msg = "eCAL Pub/Sub encoding mismatch for topic "; - msg += topic_name_; - msg += " (\'"; - msg += tencoding1; - msg += "\' <> \'"; - msg += tencoding2; - msg += "\')"; - eCAL::Logging::Log(log_level_warning, msg); - - // mark as logged - topic_info.type_missmatch_logged = true; - // and update its attributes - update_topic_info = true; - } + const auto topic_info_it = topic_info_map_.map->find(topic_info_key); - // topic type name differs - // we log the error and update the entry one time - if (!topic_info_.name.empty() - && !topic_info.info.name.empty() - && (topic_info.info.name != topic_info_.name) - ) - { - std::string ttype1 = topic_info.info.name; - std::string ttype2 = topic_info_.name; - std::replace(ttype1.begin(), ttype1.end(), '\0', '?'); - std::replace(ttype1.begin(), ttype1.end(), '\t', '?'); - std::replace(ttype2.begin(), ttype2.end(), '\0', '?'); - std::replace(ttype2.begin(), ttype2.end(), '\t', '?'); - std::string msg = "eCAL Pub/Sub type mismatch for topic "; - msg += topic_name_; - msg += " (\'"; - msg += ttype1; - msg += "\' <> \'"; - msg += ttype2; - msg += "\')"; - eCAL::Logging::Log(log_level_warning, msg); - - // mark as logged - topic_info.type_missmatch_logged = true; - // and update its attributes - update_topic_info = true; - } - - // topic type description differs - // we log the error and update the entry one time - if (!topic_info_.descriptor.empty() - && !topic_info.info.descriptor.empty() - && (topic_info.info.descriptor != topic_info_.descriptor) - ) - { - std::string msg = "eCAL Pub/Sub description mismatch for topic "; - msg += topic_name_; - eCAL::Logging::Log(log_level_warning, msg); - - // mark as logged - topic_info.type_missmatch_logged = true; - // and update its attributes - update_topic_info = true; - } - - // update topic info attributes - if (update_topic_info) - { - (*m_topic_info_map.map)[topic_name_] = topic_info; - } - - return false; + (*topic_info_map_.map)[topic_info_key] = topic_quality_info; } - bool CDescGate::RemTopicDescription(const std::string& topic_name_, const std::string& topic_id_) + void CDescGate::RemTopicDescription(STopicInfoMap& topic_info_map_, const std::string& topic_name_, const std::string& topic_id_) { - const std::unique_lock lock(m_topic_info_map.sync); - m_topic_info_map.map->remove_deprecated(); - - const auto topic_info_it = m_topic_info_map.map->find(topic_name_); - if (topic_info_it != m_topic_info_map.map->end()) - { - STopicInfoQuality& topic_info = (*m_topic_info_map.map)[topic_name_]; - if (topic_info.id == topic_id_) - { - m_topic_info_map.map->erase(topic_name_); - return true; - } - } - return false; + const std::unique_lock lock(topic_info_map_.sync); + topic_info_map_.map->remove_deprecated(); + topic_info_map_.map->erase(STopicNameId{ topic_name_, topic_id_ }); } - bool CDescGate::ApplyServiceDescription(SServiceMethodInfoMap& service_method_map_ - , const std::string& service_name_ - , const std::string& service_id_ - , const std::string& method_name_ - , const SDataTypeInformation& request_type_information_ - , const SDataTypeInformation& response_type_information_ - , const QualityFlags description_quality_) + void CDescGate::ApplyServiceDescription(SServiceMethodInfoMap& service_method_info_map_, + const std::string& service_name_, + const std::string& service_id_, + const std::string& method_name_, + const SDataTypeInformation& request_type_information_, + const SDataTypeInformation& response_type_information_, + const Util::DescQualityFlags service_quality_) { - std::tuple service_method_tuple = std::make_tuple(service_name_, method_name_); - - const std::lock_guard lock(service_method_map_.sync); - service_method_map_.map->remove_deprecated(); - - SServiceMethodInfoQuality req_service_info; - req_service_info.id = service_id_; - req_service_info.info.request_type = request_type_information_; - req_service_info.info.response_type = response_type_information_; - req_service_info.quality = description_quality_; - - // create a new entry if service is not existing and return - auto service_info_map_it = service_method_map_.map->find(service_method_tuple); - if (service_info_map_it == service_method_map_.map->end()) - { - (*service_method_map_.map)[service_method_tuple] = req_service_info; - return true; - } + const auto service_method_info_key = SServiceMethodNameId{ service_name_, service_id_, method_name_ }; - // service is existing, the requested service has a higher quality - // overwrite the existing entry with the new attributes - SServiceMethodInfoQuality service_info = (*service_info_map_it).second; - if (description_quality_ > service_info.quality) - { - (*service_method_map_.map)[service_method_tuple] = req_service_info; - return true; - } - - // the entry is existing, the requested quality is not higher - // update the timestamp of the existing entry - if (service_info.info == req_service_info.info) - { - (*service_method_map_.map)[service_method_tuple] = service_info; - return true; - } + Util::SQualityServiceMethodInformation service_quality_info; + service_quality_info.id = service_id_; + service_quality_info.info.request_type = request_type_information_; + service_quality_info.info.response_type = response_type_information_; + service_quality_info.quality = service_quality_; - return false; + const std::lock_guard lock(service_method_info_map_.sync); + service_method_info_map_.map->remove_deprecated(); + (*service_method_info_map_.map)[service_method_info_key] = service_quality_info; } - bool CDescGate::RemServiceDescription(SServiceMethodInfoMap& service_method_map_, const std::string& service_name_, const std::string& service_id_) + void CDescGate::RemServiceDescription(SServiceMethodInfoMap& service_method_info_map_, const std::string& service_name_, const std::string& service_id_) { - std::list> service_method_tuple_to_remove; + std::list service_method_infos_to_remove; - const std::lock_guard lock(service_method_map_.sync); - service_method_map_.map->remove_deprecated(); + const std::lock_guard lock(service_method_info_map_.sync); + service_method_info_map_.map->remove_deprecated(); - bool success(false); - for (auto&& service : *service_method_map_.map) + for (auto&& service_it : *service_method_info_map_.map) { - auto service_method_tuple = service.first; - if (std::get<0>(service_method_tuple) == service_name_) + const auto service_method_info = service_it.first; + if ((service_method_info.service_name == service_name_) + && (service_method_info.service_id == service_id_)) { - auto service_info = service.second; - if (service_info.id == service_id_) - { - service_method_tuple_to_remove.push_back(service_method_tuple); - success = true; - } + service_method_infos_to_remove.push_back(service_method_info); } } - for (const auto& service_method_tuple : service_method_tuple_to_remove) - { - (*service_method_map_.map).erase(service_method_tuple); - } - - return success; - } - - void CDescGate::GetServices(std::map, SServiceMethodInformation>& service_info_map_, const SServiceMethodInfoMap& service_method_map_) - { - std::map, SServiceMethodInformation> map; - - const std::lock_guard lock(service_method_map_.sync); - service_method_map_.map->remove_deprecated(); - - for (const auto& service_info : (*service_method_map_.map)) - { - map.emplace(service_info.first, service_info.second.info); - } - service_info_map_.swap(map); - } - - void CDescGate::GetServiceMethodNames(std::vector>& method_names_, const SServiceMethodInfoMap& service_method_map_) - { - method_names_.clear(); - - const std::lock_guard lock(service_method_map_.sync); - service_method_map_.map->remove_deprecated(); - method_names_.reserve(service_method_map_.map->size()); - - for (const auto& service_info : (*service_method_map_.map)) + for (const auto& service_method_info : service_method_infos_to_remove) { - method_names_.emplace_back(service_info.first); + (*service_method_info_map_.map).erase(service_method_info); } } - - bool CDescGate::GetServiceTypeNames(const std::string& service_name_, const std::string& method_name_, std::string& req_type_name_, std::string& resp_type_name_, const SServiceMethodInfoMap& service_method_map_) - { - std::tuple service_method_tuple = std::make_tuple(service_name_, method_name_); - - const std::lock_guard lock(service_method_map_.sync); - service_method_map_.map->remove_deprecated(); - auto service_info_map_it = service_method_map_.map->find(service_method_tuple); - - if (service_info_map_it == service_method_map_.map->end()) return false; - req_type_name_ = (*service_info_map_it).second.info.request_type.name; - resp_type_name_ = (*service_info_map_it).second.info.response_type.name; - return true; - } - - bool CDescGate::GetServiceDescription(const std::string& service_name_, const std::string& method_name_, std::string& req_type_desc_, std::string& resp_type_desc_, const SServiceMethodInfoMap& service_method_map_) - { - std::tuple service_method_tuple = std::make_tuple(service_name_, method_name_); - - const std::lock_guard lock(service_method_map_.sync); - service_method_map_.map->remove_deprecated(); - auto service_info_map_it = service_method_map_.map->find(service_method_tuple); - - if (service_info_map_it == service_method_map_.map->end()) return false; - req_type_desc_ = (*service_info_map_it).second.info.request_type.descriptor; - resp_type_desc_ = (*service_info_map_it).second.info.response_type.descriptor; - return true; - } } diff --git a/ecal/core/src/ecal_descgate.h b/ecal/core/src/ecal_descgate.h index 571ff37436..3be69afadb 100644 --- a/ecal/core/src/ecal_descgate.h +++ b/ecal/core/src/ecal_descgate.h @@ -26,40 +26,18 @@ #include #include -#include "ecal_global_accessors.h" -#include "ecal_def.h" #include "serialization/ecal_serialize_sample_registration.h" #include "util/ecal_expmap.h" -#include #include -#include -#include +#include #include -#include #include -#include -#include namespace eCAL { class CDescGate { - public: - // Enumeration of quality bits used for detecting how good a topic information is. - enum class QualityFlags : int - { - NO_QUALITY = 0, //!< Special value for initialization - - DESCRIPTION_AVAILABLE = 0x1 << 4, //!< Having a descriptor at all is the most important thing - INFO_COMES_FROM_CORRECT_ENTITY = 0x1 << 3, //!< The information comes from the current topic/service - //!< and has not been borrowed from another emtity, like read by a subscriber from a publisher - INFO_COMES_FROM_PRODUCER = 0x1 << 2, //!< A descriptor coming from the producer (like a publisher) is better than one from a - //!< consumer (like a subscriber), as we assume that the publisher knows best what he is publishing - INFO_COMES_FROM_THIS_PROCESS = 0x1 << 1, //!< We prefer descriptors from the current process - TYPE_AVAILABLE = 0x1 << 0, //!< Having information about the type's name available is nice but not that important to us - }; - public: CDescGate(); ~CDescGate(); @@ -67,96 +45,96 @@ namespace eCAL void Create(); void Destroy(); - void GetTopics(std::unordered_map& topic_info_map_); - void GetTopicNames(std::vector& topic_names_); - bool GetDataTypeInformation(const std::string& topic_name_, SDataTypeInformation& topic_info_); + struct STopicNameId + { + std::string topic_name; + std::string topic_id; - void GetServices(std::map, SServiceMethodInformation>& service_info_map_); - void GetServiceMethodNames(std::vector>& service_method_names_); - bool GetServiceTypeNames(const std::string& service_name_, const std::string& method_name_, std::string& req_type_name_, std::string& resp_type_name_); - bool GetServiceDescription(const std::string& service_name_, const std::string& method_name_, std::string& req_type_desc_, std::string& resp_type_desc_); + bool operator<(const STopicNameId& other) const + { + if (topic_name != other.topic_name) + return topic_name < other.topic_name; + return topic_id < other.topic_id; + } + }; - void GetClients(std::map, SServiceMethodInformation>& client_info_map_); - void GetClientMethodNames(std::vector>& client_method_names_); - bool GetClientTypeNames(const std::string& client_name_, const std::string& method_name_, std::string& req_type_name_, std::string& resp_type_name_); - bool GetClientDescription(const std::string& client_name_, const std::string& method_name_, std::string& req_type_desc_, std::string& resp_type_desc_); + using TopicNameIdMap = std::map; + TopicNameIdMap GetPublisher(); + TopicNameIdMap GetSubscriber(); - protected: - struct STopicInfoQuality + struct SServiceMethodNameId { - SDataTypeInformation info; //!< Topic info struct with type encoding, name and descriptor. - std::string id; //!< Topic ID - QualityFlags quality = QualityFlags::NO_QUALITY; //!< QualityFlags to determine whether we may overwrite the current data with better one. E.g. we prefer the description sent by a publisher over one sent by a subscriber. - bool type_missmatch_logged = false; //!< Whether we have already logged a type-missmatch - }; + std::string service_name; + std::string service_id; + std::string method_name; - struct SServiceMethodInfoQuality - { - SServiceMethodInformation info; //!< Service info struct with type names and descriptors for request and response. - std::string id; //!< Service ID - QualityFlags quality = QualityFlags::NO_QUALITY; //!< The Quality of the Info + bool operator<(const SServiceMethodNameId& other) const + { + if (service_name != other.service_name) + return service_name < other.service_name; + if (service_id != other.service_id) + return service_id < other.service_id; + return method_name < other.method_name; + } }; - // key: topic name | value: topic (type/desc), quality - using TopicInfoMap = eCAL::Util::CExpMap; //!< Map containing { TopicName -> (Type, Description, Quality) } mapping of all topics that are currently known + using ServiceMethodNameIdMap = std::map; + ServiceMethodNameIdMap GetServices(); + ServiceMethodNameIdMap GetClients(); + + protected: + using TopicInfoMap = eCAL::Util::CExpMap; struct STopicInfoMap { explicit STopicInfoMap(const std::chrono::milliseconds& timeout_) : map(std::make_unique(timeout_)) { }; - mutable std::mutex sync; //!< Mutex protecting the map - std::unique_ptr map; //!< Map containing information about each known topic + mutable std::mutex sync; + std::unique_ptr map; }; - STopicInfoMap m_topic_info_map; + STopicInfoMap m_publisher_info_map; + STopicInfoMap m_subscriber_info_map; + + TopicNameIdMap GetTopics(const STopicInfoMap& topic_map_); - // key: tup | value: request (type/desc), response (type/desc), quality - using ServiceMethodInfoMap = eCAL::Util::CExpMap, SServiceMethodInfoQuality>; //!< Map { (ServiceName, MethodName) -> ( (ReqType, ReqDescription), (RespType, RespDescription), Quality ) } mapping of all currently known services + using ServiceMethodInfoMap = eCAL::Util::CExpMap; struct SServiceMethodInfoMap { explicit SServiceMethodInfoMap(const std::chrono::milliseconds& timeout_) : map(std::make_unique(timeout_)) { }; - mutable std::mutex sync; //!< Mutex protecting the map - std::unique_ptr map; //!< Map containing information about each known service + mutable std::mutex sync; + std::unique_ptr map; }; SServiceMethodInfoMap m_service_info_map; SServiceMethodInfoMap m_client_info_map; - bool ApplySample(const Registration::Sample& sample_, eTLayerType layer_); + ServiceMethodNameIdMap CDescGate::GetServices(const SServiceMethodInfoMap& service_method_info_map_); + + void ApplySample(const Registration::Sample& sample_, eTLayerType layer_); - bool ApplyTopicDescription(const std::string& topic_name_, + void ApplyTopicDescription(STopicInfoMap& topic_info_map_, + const std::string& topic_name_, const std::string& topic_id_, const SDataTypeInformation& topic_info_, - QualityFlags description_quality_); + Util::DescQualityFlags topic_quality_); - bool RemTopicDescription(const std::string& topic_name_, - const std::string& topic_id_); + void RemTopicDescription(STopicInfoMap& topic_info_map_, + const std::string& topic_name_, + const std::string& topic_id_); - bool ApplyServiceDescription(SServiceMethodInfoMap& service_method_map_, + void ApplyServiceDescription(SServiceMethodInfoMap& service_method_info_map_, const std::string& service_name_, const std::string& service_id_, const std::string& method_name_, const SDataTypeInformation& request_type_information_, const SDataTypeInformation& response_type_information_, - QualityFlags description_quality_); - - bool RemServiceDescription(SServiceMethodInfoMap& service_method_map_, - const std::string& service_name_, - const std::string& service_id_); + Util::DescQualityFlags service_quality_); - void GetServices(std::map, SServiceMethodInformation>& service_info_map_, const SServiceMethodInfoMap& service_method_map_); - void GetServiceMethodNames(std::vector>& method_names_, const SServiceMethodInfoMap& service_method_map_); - bool GetServiceTypeNames(const std::string& service_name_, const std::string& method_name_, std::string& req_type_name_, std::string& resp_type_name_, const SServiceMethodInfoMap& service_method_map_); - bool GetServiceDescription(const std::string& service_name_, const std::string& method_name_, std::string& req_type_desc_, std::string& resp_type_desc_, const SServiceMethodInfoMap& service_method_map_); + void RemServiceDescription(SServiceMethodInfoMap& service_method_info_map_, + const std::string& service_name_, + const std::string& service_id_); }; - - constexpr inline CDescGate::QualityFlags operator~ (CDescGate::QualityFlags a) { return static_cast( ~static_cast::type>(a) ); } - constexpr inline CDescGate::QualityFlags operator| (CDescGate::QualityFlags a, CDescGate::QualityFlags b) { return static_cast( static_cast::type>(a) | static_cast::type>(b) ); } - constexpr inline CDescGate::QualityFlags operator& (CDescGate::QualityFlags a, CDescGate::QualityFlags b) { return static_cast( static_cast::type>(a) & static_cast::type>(b) ); } - constexpr inline CDescGate::QualityFlags operator^ (CDescGate::QualityFlags a, CDescGate::QualityFlags b) { return static_cast( static_cast::type>(a) ^ static_cast::type>(b) ); } - inline CDescGate::QualityFlags& operator|= (CDescGate::QualityFlags& a, CDescGate::QualityFlags b) { return reinterpret_cast( reinterpret_cast::type&>(a) |= static_cast::type>(b) ); } - inline CDescGate::QualityFlags& operator&= (CDescGate::QualityFlags& a, CDescGate::QualityFlags b) { return reinterpret_cast( reinterpret_cast::type&>(a) &= static_cast::type>(b) ); } - inline CDescGate::QualityFlags& operator^= (CDescGate::QualityFlags& a, CDescGate::QualityFlags b) { return reinterpret_cast( reinterpret_cast::type&>(a) ^= static_cast::type>(b) ); } } diff --git a/ecal/core/src/ecal_util.cpp b/ecal/core/src/ecal_util.cpp index ad7470b57e..25bc05fcde 100644 --- a/ecal/core/src/ecal_util.cpp +++ b/ecal/core/src/ecal_util.cpp @@ -28,6 +28,60 @@ #include #include +namespace +{ + std::vector GetTopicDataTypeInformation(const std::string& topic_name_, const std::multimap& data_info_multi_map_) + { + std::vector data_info_vec; + + const auto data_info_range = data_info_multi_map_.equal_range(topic_name_); + for (auto data_info_range_it = data_info_range.first; data_info_range_it != data_info_range.second; ++data_info_range_it) + { + data_info_vec.push_back(data_info_range_it->second); + } + + return data_info_vec; + } + + std::vector GetServiceTypeInformation(const std::string& service_name_, const std::string& method_name_, std::multimap, eCAL::Util::SQualityServiceMethodInformation> service_info_map_) + { + std::vector service_method_info_vec; + + const auto service_info_range = service_info_map_.equal_range(std::make_pair(service_name_, method_name_)); + for (auto service_info_range_it = service_info_range.first; service_info_range_it != service_info_range.second; ++service_info_range_it) + { + service_method_info_vec.push_back(service_info_range_it->second); + } + + return service_method_info_vec; + } + + void CopyDataTypeInfoWithQualityComparison(const std::multimap& source_multi_map_, std::unordered_map& target_map_) + { + for (const auto& source_pair : source_multi_map_) + { + const std::string& source_key = source_pair.first; + const eCAL::Util::SQualityDataTypeInformation& source_value = source_pair.second; + + auto target_it = target_map_.find(source_key); + if (target_it != target_map_.end()) + { + // key exists in target map + if (source_value.quality > target_it->second.quality) + { + // source quality is greater, overwrite + target_it->second = source_value; + } + } + else + { + // key does not exist in target map, insert source pair + target_map_.insert(source_pair); + } + } + } +} + namespace eCAL { namespace Util @@ -168,71 +222,263 @@ namespace eCAL } #endif // ECAL_CORE_MONITORING - void GetTopics(std::unordered_map& topic_info_map_) + std::multimap GetPublisher() + { + std::multimap multi_map; + if (g_descgate() == nullptr) return multi_map; + + // insert publisher into target multimap + for (const auto& topic : g_descgate()->GetPublisher()) + { + multi_map.insert(std::pair(topic.first.topic_name, topic.second)); + } + + return multi_map; + } + + std::vector GetPublisher(const std::string& topic_name_) + { + return ::GetTopicDataTypeInformation(topic_name_, GetPublisher()); + } + + std::multimap GetSubscriber() + { + std::multimap multi_map; + if (g_descgate() == nullptr) return multi_map; + + // insert subscriber into target multimap + for (const auto& topic : g_descgate()->GetSubscriber()) + { + multi_map.insert(std::pair(topic.first.topic_name, topic.second)); + } + + return multi_map; + } + + std::vector GetSubscriber(const std::string& topic_name_) + { + return ::GetTopicDataTypeInformation(topic_name_, GetSubscriber()); + } + + SDataTypeInformation GetHighestQualifiedDataTypeInformation(const std::vector& data_type_info_vec_) + { + SQualityDataTypeInformation quality_info; + for (const auto& info : data_type_info_vec_) + { + if (info.quality > quality_info.quality) + { + quality_info = info; + } + } + return quality_info.info; + } + + ECAL_API std::multimap, SQualityServiceMethodInformation> GetServices() + { + std::multimap, SQualityServiceMethodInformation> multi_map; + if (g_descgate() == nullptr) return multi_map; + + // insert services into target multimap + for (const auto& service : g_descgate()->GetServices()) + { + multi_map.insert(std::pair, SQualityServiceMethodInformation>(std::make_tuple(service.first.service_name, service.first.method_name), service.second)); + } + return multi_map; + } + + ECAL_API std::multimap, SQualityServiceMethodInformation> GetClients() + { + std::multimap, SQualityServiceMethodInformation> multi_map; + if (g_descgate() == nullptr) return multi_map; + + // insert clients into target multimap + for (const auto& client : g_descgate()->GetClients()) + { + multi_map.insert(std::pair, SQualityServiceMethodInformation>(std::make_tuple(client.first.service_name, client.first.method_name), client.second)); + } + return multi_map; + } + + SServiceMethodInformation GetHighestQualifiedServiceMethodInformation(const std::vector& service_method_info_vec_) + { + SQualityServiceMethodInformation quality_info; + for (const auto& info : service_method_info_vec_) + { + if (info.quality > quality_info.quality) + { + quality_info = info; + } + } + return quality_info.info; + } + + void GetTopics(std::unordered_map& data_type_info_map_) + { + std::unordered_map qualified_data_type_info_map; + GetTopics(qualified_data_type_info_map); + + // transform into target map + for (const auto& qualified_data_type_info : qualified_data_type_info_map) + { + data_type_info_map_.insert(std::pair(qualified_data_type_info.first, qualified_data_type_info.second.info)); + } + } + + void GetTopics(std::unordered_map& qualified_data_type_info_map_) { if (g_descgate() == nullptr) return; - g_descgate()->GetTopics(topic_info_map_); + + std::multimap merged_pub_sub_map; + + // insert publisher + for (const auto& topic : g_descgate()->GetPublisher()) + { + merged_pub_sub_map.insert(std::pair(topic.first.topic_name, topic.second)); + } + + // insert subscriber + for (const auto& topic : g_descgate()->GetSubscriber()) + { + merged_pub_sub_map.insert(std::pair(topic.first.topic_name, topic.second)); + } + + // transform into a map with the highest qualified data type information + ::CopyDataTypeInfoWithQualityComparison(merged_pub_sub_map, qualified_data_type_info_map_); } void GetTopicNames(std::vector& topic_names_) { - if (g_descgate() == nullptr) return; - g_descgate()->GetTopicNames(topic_names_); + // get publisher & subscriber multi maps + auto pub_multi_map = GetPublisher(); + auto sub_multi_map = GetSubscriber(); + + // filter out unique topic names into a set + std::set set; + for (const auto& publisher : pub_multi_map) + { + set.insert(publisher.first); + } + for (const auto& subscriber : sub_multi_map) + { + set.insert(subscriber.first); + } + + // transform set into target vector + topic_names_ = std::vector(set.begin(), set.end()); } bool GetTopicDataTypeInformation(const std::string& topic_name_, SDataTypeInformation& topic_info_) { - if (g_descgate() == nullptr) return(false); - return(g_descgate()->GetDataTypeInformation(topic_name_, topic_info_)); + auto info_vec = GetPublisher(topic_name_); + const auto sub_info_vec = GetSubscriber(topic_name_); + + info_vec.insert(info_vec.end(), sub_info_vec.begin(), sub_info_vec.end()); + topic_info_ = GetHighestQualifiedDataTypeInformation(sub_info_vec); + + return !info_vec.empty(); } void GetServices(std::map, SServiceMethodInformation>& service_info_map_) { - if (g_descgate() == nullptr) return; - g_descgate()->GetServices(service_info_map_); + // TODO with comparison } void GetServiceMethodNames(std::vector>& service_method_names_) { - if (g_descgate() == nullptr) return; - g_descgate()->GetServiceMethodNames(service_method_names_); + // TODO with comparison } bool GetServiceTypeNames(const std::string& service_name_, const std::string& method_name_, std::string& req_type_, std::string& resp_type_) { - if (g_descgate() == nullptr) return(false); - return(g_descgate()->GetServiceTypeNames(service_name_, method_name_, req_type_, resp_type_)); + std::vector service_method_info_vec = GetServiceTypeInformation(service_name_, method_name_, GetServices()); + + SServiceMethodInformation service_method_info = GetHighestQualifiedServiceMethodInformation(service_method_info_vec); + req_type_ = service_method_info.request_type.name; + resp_type_ = service_method_info.response_type.name; + + return !service_method_info_vec.empty(); } bool GetServiceDescription(const std::string& service_name_, const std::string& method_name_, std::string& req_desc_, std::string& resp_desc_) { - if (g_descgate() == nullptr) return(false); - return(g_descgate()->GetServiceDescription(service_name_, method_name_, req_desc_, resp_desc_)); + std::vector service_method_info_vec = GetServiceTypeInformation(service_name_, method_name_, GetServices()); + + SServiceMethodInformation service_method_info = GetHighestQualifiedServiceMethodInformation(service_method_info_vec); + req_desc_ = service_method_info.request_type.descriptor; + resp_desc_ = service_method_info.response_type.descriptor; + + return !service_method_info_vec.empty(); } void GetClients(std::map, SServiceMethodInformation>& client_info_map_) { - if (g_descgate() == nullptr) return; - g_descgate()->GetClients(client_info_map_); + // TODO: Implement this again } void GetClientMethodNames(std::vector>& client_method_names_) { - if (g_descgate() == nullptr) return; - g_descgate()->GetClientMethodNames(client_method_names_); + // TODO: Implement this again } bool GetClientTypeNames(const std::string& client_name_, const std::string& method_name_, std::string& req_type_, std::string& resp_type_) { - if (g_descgate() == nullptr) return(false); - return(g_descgate()->GetClientTypeNames(client_name_, method_name_, req_type_, resp_type_)); + std::vector service_method_info_vec = GetServiceTypeInformation(client_name_, method_name_, GetClients()); + + SServiceMethodInformation service_method_info = GetHighestQualifiedServiceMethodInformation(service_method_info_vec); + req_type_ = service_method_info.request_type.name; + resp_type_ = service_method_info.response_type.name; + + return !service_method_info_vec.empty(); } bool GetClientDescription(const std::string& client_name_, const std::string& method_name_, std::string& req_desc_, std::string& resp_desc_) { - if (g_descgate() == nullptr) return(false); - return(g_descgate()->GetClientDescription(client_name_, method_name_, req_desc_, resp_desc_)); + std::vector service_method_info_vec = GetServiceTypeInformation(client_name_, method_name_, GetClients()); + + SServiceMethodInformation service_method_info = GetHighestQualifiedServiceMethodInformation(service_method_info_vec); + req_desc_ = service_method_info.request_type.descriptor; + resp_desc_ = service_method_info.response_type.descriptor; + + return !service_method_info_vec.empty(); + } + +#if 0 + std::multimap GetTopics() + { + std::multimap multi_map; + if (g_descgate() == nullptr) return multi_map; + + // insert publisher topics + for (const auto& topic : g_descgate()->GetPublisher()) + { + multi_map.insert(std::pair(topic.first.topic_name, topic.second)); + } + + // insert subscriber topics + for (const auto& topic : g_descgate()->GetSubscriber()) + { + multi_map.insert(std::pair(topic.first.topic_name, topic.second)); + } + + return multi_map; + } + + std::set GetTopicNames() + { + // get all topics as multimap + std::multimap topic_info_multi_map = GetTopics(); + + // filter out unique topic names into a set + std::set set; + for (const auto& topic : topic_info_multi_map) + { + set.insert(topic.first); + } + + // return set + return set; } +#endif std::pair SplitCombinedTopicType(const std::string& combined_topic_type_) { From 62a2d24aeaaa662dd262ea79d92076a8eeefde0a Mon Sep 17 00:00:00 2001 From: rex-schilasky <49162693+rex-schilasky@users.noreply.github.com> Date: Fri, 12 Apr 2024 17:01:45 +0200 Subject: [PATCH 05/27] minor fixes --- ecal/core/src/ecal_descgate.h | 2 +- ecal/core/src/ecal_util.cpp | 14 +++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/ecal/core/src/ecal_descgate.h b/ecal/core/src/ecal_descgate.h index 3be69afadb..e8b32c58fc 100644 --- a/ecal/core/src/ecal_descgate.h +++ b/ecal/core/src/ecal_descgate.h @@ -111,7 +111,7 @@ namespace eCAL SServiceMethodInfoMap m_service_info_map; SServiceMethodInfoMap m_client_info_map; - ServiceMethodNameIdMap CDescGate::GetServices(const SServiceMethodInfoMap& service_method_info_map_); + ServiceMethodNameIdMap GetServices(const SServiceMethodInfoMap& service_method_info_map_); void ApplySample(const Registration::Sample& sample_, eTLayerType layer_); diff --git a/ecal/core/src/ecal_util.cpp b/ecal/core/src/ecal_util.cpp index 25bc05fcde..ed6198e3a8 100644 --- a/ecal/core/src/ecal_util.cpp +++ b/ecal/core/src/ecal_util.cpp @@ -56,15 +56,17 @@ namespace return service_method_info_vec; } - void CopyDataTypeInfoWithQualityComparison(const std::multimap& source_multi_map_, std::unordered_map& target_map_) + std::unordered_map GetQualifiedMap(const std::multimap& source_multi_map_) { + std::unordered_map target_map; + for (const auto& source_pair : source_multi_map_) { const std::string& source_key = source_pair.first; const eCAL::Util::SQualityDataTypeInformation& source_value = source_pair.second; - auto target_it = target_map_.find(source_key); - if (target_it != target_map_.end()) + auto target_it = target_map.find(source_key); + if (target_it != target_map.end()) { // key exists in target map if (source_value.quality > target_it->second.quality) @@ -76,9 +78,11 @@ namespace else { // key does not exist in target map, insert source pair - target_map_.insert(source_pair); + target_map.insert(source_pair); } } + + return target_map; } } @@ -343,7 +347,7 @@ namespace eCAL } // transform into a map with the highest qualified data type information - ::CopyDataTypeInfoWithQualityComparison(merged_pub_sub_map, qualified_data_type_info_map_); + qualified_data_type_info_map_ = GetQualifiedMap(merged_pub_sub_map); } void GetTopicNames(std::vector& topic_names_) From 3e67a72e6c87eb2b8edb5aa5c17db5be4c269a8c Mon Sep 17 00:00:00 2001 From: rex-schilasky <49162693+rex-schilasky@users.noreply.github.com> Date: Fri, 12 Apr 2024 22:20:25 +0200 Subject: [PATCH 06/27] legacy gettopics_xy API reimplemented --- ecal/core/include/ecal/ecal_util.h | 32 +++++++--- ecal/core/src/ecal_util.cpp | 63 ++++++------------- .../cpp/util_test/src/util_gettopics.cpp | 23 ++----- 3 files changed, 50 insertions(+), 68 deletions(-) diff --git a/ecal/core/include/ecal/ecal_util.h b/ecal/core/include/ecal/ecal_util.h index 1d8b7143ed..7250b9e25c 100644 --- a/ecal/core/include/ecal/ecal_util.h +++ b/ecal/core/include/ecal/ecal_util.h @@ -216,13 +216,15 @@ namespace eCAL * @brief Get complete topic map. * * @param topic_info_map_ Map to store the datatype information. + * Map { TopicName -> SDataTypeInformation } mapping of all currently known publisher/subscriber. **/ ECAL_API void GetTopics(std::unordered_map& data_type_info_map_); /** * @brief Get complete qualified topic map. * - * @param topic_info_map_ Map to store the qualified datatype information. + * @param qualfied_data_type_info_map_ Map to store the qualified datatype information. + * Map { TopicName -> SQualityDataTypeInformation } mapping of all currently known publisher/subscriber. **/ ECAL_API void GetTopics(std::unordered_map& qualfied_data_type_info_map_); @@ -244,12 +246,20 @@ namespace eCAL ECAL_API bool GetTopicDataTypeInformation(const std::string& topic_name_, SDataTypeInformation& topic_info_); /** - * @brief Get complete service map (including request and response types and descriptions). + * @brief Get complete service map. * - * @param service_info_map_ Map to store the datatype descriptions. + * @param service_info_map_ Map to store the service/method descriptions. * Map { (ServiceName, MethodName) -> SServiceMethodInformation } mapping of all currently known services. **/ - ECAL_API void GetServices(std::map, SServiceMethodInformation>& service_info_map_); + ECAL_API void GetServices(std::map, SServiceMethodInformation>& service_info_map_); + + /** + * @brief Get complete qualified service map. + * + * @param qualified_service_info_map_ Map to store the qualified service/method descriptions. + * Map { (ServiceName, MethodName) -> SQualityServiceMethodInformation } mapping of all currently known services. + **/ + ECAL_API void GetServices(std::map, SQualityServiceMethodInformation>& qualified_service_info_map_); /** * @brief Get all service/method names. @@ -283,13 +293,21 @@ namespace eCAL ECAL_API bool GetServiceDescription(const std::string& service_name_, const std::string& method_name_, std::string& req_desc_, std::string& resp_desc_); /** - * @brief Get complete client map (including request and response types and descriptions). + * @brief Get complete client map. * - * @param client_info_map_ Map to store the datatype descriptions. - * Map { (ClientName, MethodName) -> ( (ReqType, ReqDescription), (RespType, RespDescription) ) } mapping of all currently known clients. + * @param client_info_map_ Map to store the client/method descriptions. + * Map { (ClientName, MethodName) -> SServiceMethodInformation } mapping of all currently known clients. **/ ECAL_API void GetClients(std::map, SServiceMethodInformation>& client_info_map_); + /** + * @brief Get complete qualified client map. + * + * @param qualified_client_info_map_ Map to store the qualified client/method descriptions. + * Map { (ClientName, MethodName) -> SQualityServiceMethodInformation } mapping of all currently known clients. + **/ + ECAL_API void GetClients(std::map, SQualityServiceMethodInformation>& qualified_client_info_map_); + /** * @brief Get all client/method names. * diff --git a/ecal/core/src/ecal_util.cpp b/ecal/core/src/ecal_util.cpp index ed6198e3a8..ddae4cf535 100644 --- a/ecal/core/src/ecal_util.cpp +++ b/ecal/core/src/ecal_util.cpp @@ -318,6 +318,8 @@ namespace eCAL void GetTopics(std::unordered_map& data_type_info_map_) { + data_type_info_map_.clear(); + std::unordered_map qualified_data_type_info_map; GetTopics(qualified_data_type_info_map); @@ -330,6 +332,7 @@ namespace eCAL void GetTopics(std::unordered_map& qualified_data_type_info_map_) { + qualified_data_type_info_map_.clear(); if (g_descgate() == nullptr) return; std::multimap merged_pub_sub_map; @@ -352,6 +355,8 @@ namespace eCAL void GetTopicNames(std::vector& topic_names_) { + topic_names_.clear(); + // get publisher & subscriber multi maps auto pub_multi_map = GetPublisher(); auto sub_multi_map = GetSubscriber(); @@ -377,19 +382,24 @@ namespace eCAL const auto sub_info_vec = GetSubscriber(topic_name_); info_vec.insert(info_vec.end(), sub_info_vec.begin(), sub_info_vec.end()); - topic_info_ = GetHighestQualifiedDataTypeInformation(sub_info_vec); + topic_info_ = GetHighestQualifiedDataTypeInformation(info_vec); return !info_vec.empty(); } void GetServices(std::map, SServiceMethodInformation>& service_info_map_) { - // TODO with comparison + // TODO: Implement this with comparison + } + + void GetServices(std::map, SQualityServiceMethodInformation>& qualified_service_info_map_) + { + // TODO: Implement this } void GetServiceMethodNames(std::vector>& service_method_names_) { - // TODO with comparison + // TODO: Implement this with comparison } bool GetServiceTypeNames(const std::string& service_name_, const std::string& method_name_, std::string& req_type_, std::string& resp_type_) @@ -416,12 +426,17 @@ namespace eCAL void GetClients(std::map, SServiceMethodInformation>& client_info_map_) { - // TODO: Implement this again + // TODO: Implement this with comparison + } + + void GetClients(std::map, SQualityServiceMethodInformation>& qualified_client_info_map_) + { + // TODO: Implement this } void GetClientMethodNames(std::vector>& client_method_names_) { - // TODO: Implement this again + // TODO: Implement this with comparison } bool GetClientTypeNames(const std::string& client_name_, const std::string& method_name_, std::string& req_type_, std::string& resp_type_) @@ -446,44 +461,6 @@ namespace eCAL return !service_method_info_vec.empty(); } -#if 0 - std::multimap GetTopics() - { - std::multimap multi_map; - if (g_descgate() == nullptr) return multi_map; - - // insert publisher topics - for (const auto& topic : g_descgate()->GetPublisher()) - { - multi_map.insert(std::pair(topic.first.topic_name, topic.second)); - } - - // insert subscriber topics - for (const auto& topic : g_descgate()->GetSubscriber()) - { - multi_map.insert(std::pair(topic.first.topic_name, topic.second)); - } - - return multi_map; - } - - std::set GetTopicNames() - { - // get all topics as multimap - std::multimap topic_info_multi_map = GetTopics(); - - // filter out unique topic names into a set - std::set set; - for (const auto& topic : topic_info_multi_map) - { - set.insert(topic.first); - } - - // return set - return set; - } -#endif - std::pair SplitCombinedTopicType(const std::string& combined_topic_type_) { auto pos = combined_topic_type_.find(':'); diff --git a/ecal/tests/cpp/util_test/src/util_gettopics.cpp b/ecal/tests/cpp/util_test/src/util_gettopics.cpp index bb50a2ab7d..f31efadbac 100644 --- a/ecal/tests/cpp/util_test/src/util_gettopics.cpp +++ b/ecal/tests/cpp/util_test/src/util_gettopics.cpp @@ -88,36 +88,23 @@ TEST(core_cpp_util, GetTopics) EXPECT_EQ(topic_info_map.size(), 5); // now destroy publisher pub1 and subscriber sub1 - // after map expiration time the entities p12 and sub12 - // should replace them (by overwriting type name and description) + // the entities pub12 and sub12 should replace them + // by overwriting their type names and descriptions pub1.Destroy(); sub1.Destroy(); - { - eCAL::SDataTypeInformation utils_topic_info; - eCAL::Util::GetTopicDataTypeInformation("A1", utils_topic_info); - EXPECT_EQ(false, eCAL::Util::GetTopicDataTypeInformation("A1", utils_topic_info)); - EXPECT_EQ(false, eCAL::Util::GetTopicDataTypeInformation("B1", utils_topic_info)); - } - - // 2 registration cycles - eCAL::Process::SleepMS(2 * CMN_REGISTRATION_REFRESH); - - // update map - eCAL::Util::GetTopics(topic_info_map); - - // size should be 5 again (because of pub1.2 and sub1.2 should have replaced pub1 and sub1 attributes now) + // size should be 5 again (because of pub12 and sub12 should have replaced pub1 and sub1 attributes now) EXPECT_EQ(topic_info_map.size(), 5); // check overwritten attributes { eCAL::SDataTypeInformation utils_topic_info; - eCAL::Util::GetTopicDataTypeInformation("A1", utils_topic_info); + EXPECT_EQ(true, eCAL::Util::GetTopicDataTypeInformation("A1", utils_topic_info)); EXPECT_EQ(utils_topic_info, info_A1_2); } { eCAL::SDataTypeInformation utils_topic_info; - eCAL::Util::GetTopicDataTypeInformation("B1", utils_topic_info); + EXPECT_EQ(true, eCAL::Util::GetTopicDataTypeInformation("B1", utils_topic_info)); EXPECT_EQ(utils_topic_info, info_B1_2); } } From 12351f8a46a6b6812299ea3445982232d8a26426 Mon Sep 17 00:00:00 2001 From: rex-schilasky <49162693+rex-schilasky@users.noreply.github.com> Date: Sun, 14 Apr 2024 20:51:23 +0200 Subject: [PATCH 07/27] next refactoring --- ecal/core/include/ecal/ecal_util.h | 29 +- ecal/core/src/ecal_descgate.cpp | 48 +-- ecal/core/src/ecal_descgate.h | 118 ++++---- ecal/core/src/ecal_util.cpp | 282 ++++++++++++------ .../cpp/util_test/src/util_getclients.cpp | 10 +- .../cpp/util_test/src/util_gettopics.cpp | 8 +- 6 files changed, 296 insertions(+), 199 deletions(-) diff --git a/ecal/core/include/ecal/ecal_util.h b/ecal/core/include/ecal/ecal_util.h index 7250b9e25c..7eabde9340 100644 --- a/ecal/core/include/ecal/ecal_util.h +++ b/ecal/core/include/ecal/ecal_util.h @@ -31,7 +31,6 @@ #include #include #include -#include #include #include @@ -50,14 +49,14 @@ namespace eCAL }; inline DescQualityFlags& operator|= (DescQualityFlags& a, DescQualityFlags b) { return reinterpret_cast(reinterpret_cast::type&>(a) |= static_cast::type>(b)); } - struct SQualityDataTypeInformation + struct SQualityTopicInfo { std::string id; SDataTypeInformation info; DescQualityFlags quality = DescQualityFlags::NO_QUALITY; }; - struct SQualityServiceMethodInformation + struct SQualityServiceInfo { std::string id; SServiceMethodInformation info; @@ -153,7 +152,7 @@ namespace eCAL * * @return MultiMap containing the qualified datatype information and the topic id's. **/ - ECAL_API std::multimap GetPublisher(); + ECAL_API std::multimap GetPublisher(); /** * @brief Get data type information with quality and topic id for this publisher. @@ -162,14 +161,14 @@ namespace eCAL * * @return Vector containing the qualified datatype information for this publisher. **/ - ECAL_API std::vector GetPublisher(const std::string& topic_name_); + ECAL_API std::vector GetPublisher(const std::string& topic_name_); /** * @brief Get complete snapshot of data type information with quality and topic id for all known subscriber. * * @return MultiMap containing the qualified datatype information and the topic id's. **/ - ECAL_API std::multimap GetSubscriber(); + ECAL_API std::multimap GetSubscriber(); /** * @brief Get data type information with quality and topic id for this subscriber. @@ -178,7 +177,7 @@ namespace eCAL * * @return Vector containing the qualified datatype information for this subscriber. **/ - ECAL_API std::vector GetSubscriber(const std::string& topic_name_); + ECAL_API std::vector GetSubscriber(const std::string& topic_name_); /** * @brief Get highest qualified data type information out of a vector of qualified data type information. @@ -187,21 +186,21 @@ namespace eCAL * * @return Highest qualified data type information. **/ - ECAL_API SDataTypeInformation GetHighestQualifiedDataTypeInformation(const std::vector& data_type_info_vec_); + ECAL_API SDataTypeInformation GetHighestQualityDataTypeInformation(const std::vector& data_type_info_vec_); /** * @brief Get complete snapshot of service method information with quality and service id for all known services. * * @return MultiMap containing the qualified datatype information and the service id's. **/ - ECAL_API std::multimap, SQualityServiceMethodInformation> GetServices(); + ECAL_API std::multimap, SQualityServiceInfo> GetServices(); /** * @brief Get complete snapshot of service method information with quality and client id for all known clients. * * @return MultiMap containing the qualified datatype information and the client id's. **/ - ECAL_API std::multimap, SQualityServiceMethodInformation> GetClients(); + ECAL_API std::multimap, SQualityServiceInfo> GetClients(); /** * @brief Get highest qualified service method type information out of a vector of qualified service method information. @@ -210,7 +209,7 @@ namespace eCAL * * @return Highest qualified service method information. **/ - ECAL_API SServiceMethodInformation GetHighestQualifiedServiceMethodInformation(const std::vector& service_method_info_vec_); + ECAL_API SServiceMethodInformation GetHighestQualityServiceMethodInformation(const std::vector& service_method_info_vec_); /** * @brief Get complete topic map. @@ -218,7 +217,7 @@ namespace eCAL * @param topic_info_map_ Map to store the datatype information. * Map { TopicName -> SDataTypeInformation } mapping of all currently known publisher/subscriber. **/ - ECAL_API void GetTopics(std::unordered_map& data_type_info_map_); + ECAL_API void GetTopics(std::map& data_type_info_map_); /** * @brief Get complete qualified topic map. @@ -226,7 +225,7 @@ namespace eCAL * @param qualfied_data_type_info_map_ Map to store the qualified datatype information. * Map { TopicName -> SQualityDataTypeInformation } mapping of all currently known publisher/subscriber. **/ - ECAL_API void GetTopics(std::unordered_map& qualfied_data_type_info_map_); + ECAL_API void GetTopics(std::map& qualfied_data_type_info_map_); /** * @brief Get all topic names. @@ -259,7 +258,7 @@ namespace eCAL * @param qualified_service_info_map_ Map to store the qualified service/method descriptions. * Map { (ServiceName, MethodName) -> SQualityServiceMethodInformation } mapping of all currently known services. **/ - ECAL_API void GetServices(std::map, SQualityServiceMethodInformation>& qualified_service_info_map_); + ECAL_API void GetServices(std::map, SQualityServiceInfo>& qualified_service_info_map_); /** * @brief Get all service/method names. @@ -306,7 +305,7 @@ namespace eCAL * @param qualified_client_info_map_ Map to store the qualified client/method descriptions. * Map { (ClientName, MethodName) -> SQualityServiceMethodInformation } mapping of all currently known clients. **/ - ECAL_API void GetClients(std::map, SQualityServiceMethodInformation>& qualified_client_info_map_); + ECAL_API void GetClients(std::map, SQualityServiceInfo>& qualified_client_info_map_); /** * @brief Get all client/method names. diff --git a/ecal/core/src/ecal_descgate.cpp b/ecal/core/src/ecal_descgate.cpp index d6b40d3c13..a54ac96f77 100644 --- a/ecal/core/src/ecal_descgate.cpp +++ b/ecal/core/src/ecal_descgate.cpp @@ -97,31 +97,31 @@ namespace eCAL #endif } - CDescGate::TopicNameIdMap CDescGate::GetPublisher() + QualityTopicIdMap CDescGate::GetPublisher() { return GetTopics(m_publisher_info_map); } - CDescGate::TopicNameIdMap CDescGate::GetSubscriber() + QualityTopicIdMap CDescGate::GetSubscriber() { return GetTopics(m_subscriber_info_map); } - CDescGate::ServiceMethodNameIdMap CDescGate::GetServices() + QualityServiceIdMap CDescGate::GetServices() { return GetServices(m_service_info_map); } - CDescGate::ServiceMethodNameIdMap CDescGate::GetClients() + QualityServiceIdMap CDescGate::GetClients() { return GetServices(m_client_info_map); } - CDescGate::TopicNameIdMap CDescGate::GetTopics(const STopicInfoMap& topic_map_) + QualityTopicIdMap CDescGate::GetTopics(const SQualityTopicIdMap& topic_map_) { - TopicNameIdMap map; + QualityTopicIdMap map; - const std::lock_guard lock(topic_map_.sync); + const std::lock_guard lock(topic_map_.mtx); topic_map_.map->remove_deprecated(); for (const auto& topic_map_it : (*topic_map_.map)) @@ -131,11 +131,11 @@ namespace eCAL return map; } - CDescGate::ServiceMethodNameIdMap CDescGate::GetServices(const SServiceMethodInfoMap& service_method_info_map_) + QualityServiceIdMap CDescGate::GetServices(const SQualityServiceIdMap& service_method_info_map_) { - ServiceMethodNameIdMap map; + QualityServiceIdMap map; - const std::lock_guard lock(service_method_info_map_.sync); + const std::lock_guard lock(service_method_info_map_.mtx); service_method_info_map_.map->remove_deprecated(); for (const auto& service_method_info_map_it : (*service_method_info_map_.map)) @@ -210,20 +210,20 @@ namespace eCAL } } - void CDescGate::ApplyTopicDescription(STopicInfoMap& topic_info_map_, + void CDescGate::ApplyTopicDescription(SQualityTopicIdMap& topic_info_map_, const std::string& topic_name_, const std::string& topic_id_, const SDataTypeInformation& topic_info_, Util::DescQualityFlags topic_quality_) { - const auto topic_info_key = STopicNameId{ topic_name_, topic_id_ }; + const auto topic_info_key = STopicIdKey{ topic_name_, topic_id_ }; - Util::SQualityDataTypeInformation topic_quality_info; + Util::SQualityTopicInfo topic_quality_info; topic_quality_info.id = topic_id_; topic_quality_info.info = topic_info_; topic_quality_info.quality = topic_quality_; - const std::unique_lock lock(topic_info_map_.sync); + const std::unique_lock lock(topic_info_map_.mtx); topic_info_map_.map->remove_deprecated(); const auto topic_info_it = topic_info_map_.map->find(topic_info_key); @@ -231,14 +231,14 @@ namespace eCAL (*topic_info_map_.map)[topic_info_key] = topic_quality_info; } - void CDescGate::RemTopicDescription(STopicInfoMap& topic_info_map_, const std::string& topic_name_, const std::string& topic_id_) + void CDescGate::RemTopicDescription(SQualityTopicIdMap& topic_info_map_, const std::string& topic_name_, const std::string& topic_id_) { - const std::unique_lock lock(topic_info_map_.sync); + const std::unique_lock lock(topic_info_map_.mtx); topic_info_map_.map->remove_deprecated(); - topic_info_map_.map->erase(STopicNameId{ topic_name_, topic_id_ }); + topic_info_map_.map->erase(STopicIdKey{ topic_name_, topic_id_ }); } - void CDescGate::ApplyServiceDescription(SServiceMethodInfoMap& service_method_info_map_, + void CDescGate::ApplyServiceDescription(SQualityServiceIdMap& service_method_info_map_, const std::string& service_name_, const std::string& service_id_, const std::string& method_name_, @@ -246,24 +246,24 @@ namespace eCAL const SDataTypeInformation& response_type_information_, const Util::DescQualityFlags service_quality_) { - const auto service_method_info_key = SServiceMethodNameId{ service_name_, service_id_, method_name_ }; + const auto service_method_info_key = SServiceIdKey{ service_name_, service_id_, method_name_ }; - Util::SQualityServiceMethodInformation service_quality_info; + Util::SQualityServiceInfo service_quality_info; service_quality_info.id = service_id_; service_quality_info.info.request_type = request_type_information_; service_quality_info.info.response_type = response_type_information_; service_quality_info.quality = service_quality_; - const std::lock_guard lock(service_method_info_map_.sync); + const std::lock_guard lock(service_method_info_map_.mtx); service_method_info_map_.map->remove_deprecated(); (*service_method_info_map_.map)[service_method_info_key] = service_quality_info; } - void CDescGate::RemServiceDescription(SServiceMethodInfoMap& service_method_info_map_, const std::string& service_name_, const std::string& service_id_) + void CDescGate::RemServiceDescription(SQualityServiceIdMap& service_method_info_map_, const std::string& service_name_, const std::string& service_id_) { - std::list service_method_infos_to_remove; + std::list service_method_infos_to_remove; - const std::lock_guard lock(service_method_info_map_.sync); + const std::lock_guard lock(service_method_info_map_.mtx); service_method_info_map_.map->remove_deprecated(); for (auto&& service_it : *service_method_info_map_.map) diff --git a/ecal/core/src/ecal_descgate.h b/ecal/core/src/ecal_descgate.h index e8b32c58fc..a6475e3585 100644 --- a/ecal/core/src/ecal_descgate.h +++ b/ecal/core/src/ecal_descgate.h @@ -36,96 +36,98 @@ namespace eCAL { + struct STopicIdKey + { + std::string topic_name; + std::string topic_id; + + bool operator<(const STopicIdKey& other) const + { + if (topic_name != other.topic_name) + return topic_name < other.topic_name; + return topic_id < other.topic_id; + } + }; + + struct SServiceIdKey + { + std::string service_name; + std::string service_id; + std::string method_name; + + bool operator<(const SServiceIdKey& other) const + { + if (service_name != other.service_name) + return service_name < other.service_name; + if (service_id != other.service_id) + return service_id < other.service_id; + return method_name < other.method_name; + } + }; + + using QualityTopicIdMap = std::map; + using QualityServiceIdMap = std::map; + class CDescGate { public: + CDescGate(); ~CDescGate(); void Create(); void Destroy(); - struct STopicNameId - { - std::string topic_name; - std::string topic_id; - - bool operator<(const STopicNameId& other) const - { - if (topic_name != other.topic_name) - return topic_name < other.topic_name; - return topic_id < other.topic_id; - } - }; - - using TopicNameIdMap = std::map; - TopicNameIdMap GetPublisher(); - TopicNameIdMap GetSubscriber(); - - struct SServiceMethodNameId - { - std::string service_name; - std::string service_id; - std::string method_name; - - bool operator<(const SServiceMethodNameId& other) const - { - if (service_name != other.service_name) - return service_name < other.service_name; - if (service_id != other.service_id) - return service_id < other.service_id; - return method_name < other.method_name; - } - }; + QualityTopicIdMap GetPublisher(); + QualityTopicIdMap GetSubscriber(); - using ServiceMethodNameIdMap = std::map; - ServiceMethodNameIdMap GetServices(); - ServiceMethodNameIdMap GetClients(); + QualityServiceIdMap GetServices(); + QualityServiceIdMap GetClients(); protected: - using TopicInfoMap = eCAL::Util::CExpMap; - struct STopicInfoMap + using QualityTopicIdExpMap = eCAL::Util::CExpMap; + struct SQualityTopicIdMap { - explicit STopicInfoMap(const std::chrono::milliseconds& timeout_) : - map(std::make_unique(timeout_)) + explicit SQualityTopicIdMap(const std::chrono::milliseconds& timeout_) : + map(std::make_unique(timeout_)) { }; - mutable std::mutex sync; - std::unique_ptr map; + mutable std::mutex mtx; + std::unique_ptr map; }; - STopicInfoMap m_publisher_info_map; - STopicInfoMap m_subscriber_info_map; - - TopicNameIdMap GetTopics(const STopicInfoMap& topic_map_); - using ServiceMethodInfoMap = eCAL::Util::CExpMap; - struct SServiceMethodInfoMap + using QualityServiceIdExpMap = eCAL::Util::CExpMap; + struct SQualityServiceIdMap { - explicit SServiceMethodInfoMap(const std::chrono::milliseconds& timeout_) : - map(std::make_unique(timeout_)) + explicit SQualityServiceIdMap(const std::chrono::milliseconds& timeout_) : + map(std::make_unique(timeout_)) { }; - mutable std::mutex sync; - std::unique_ptr map; + mutable std::mutex mtx; + std::unique_ptr map; }; - SServiceMethodInfoMap m_service_info_map; - SServiceMethodInfoMap m_client_info_map; - ServiceMethodNameIdMap GetServices(const SServiceMethodInfoMap& service_method_info_map_); + SQualityTopicIdMap m_publisher_info_map; + SQualityTopicIdMap m_subscriber_info_map; + SQualityServiceIdMap m_service_info_map; + SQualityServiceIdMap m_client_info_map; + + QualityTopicIdMap GetTopics(const SQualityTopicIdMap& topic_map_); + QualityServiceIdMap GetServices(const SQualityServiceIdMap& service_method_info_map_); void ApplySample(const Registration::Sample& sample_, eTLayerType layer_); - void ApplyTopicDescription(STopicInfoMap& topic_info_map_, + void ApplyTopicDescription(SQualityTopicIdMap& topic_info_map_, const std::string& topic_name_, const std::string& topic_id_, const SDataTypeInformation& topic_info_, Util::DescQualityFlags topic_quality_); - void RemTopicDescription(STopicInfoMap& topic_info_map_, + void RemTopicDescription(SQualityTopicIdMap& topic_info_map_, const std::string& topic_name_, const std::string& topic_id_); - void ApplyServiceDescription(SServiceMethodInfoMap& service_method_info_map_, + void ApplyServiceDescription(SQualityServiceIdMap& service_method_info_map_, const std::string& service_name_, const std::string& service_id_, const std::string& method_name_, @@ -133,7 +135,7 @@ namespace eCAL const SDataTypeInformation& response_type_information_, Util::DescQualityFlags service_quality_); - void RemServiceDescription(SServiceMethodInfoMap& service_method_info_map_, + void RemServiceDescription(SQualityServiceIdMap& service_method_info_map_, const std::string& service_name_, const std::string& service_id_); }; diff --git a/ecal/core/src/ecal_util.cpp b/ecal/core/src/ecal_util.cpp index ddae4cf535..25d155150f 100644 --- a/ecal/core/src/ecal_util.cpp +++ b/ecal/core/src/ecal_util.cpp @@ -24,48 +24,72 @@ #include #include -#include #include #include namespace { - std::vector GetTopicDataTypeInformation(const std::string& topic_name_, const std::multimap& data_info_multi_map_) + /** + * @brief Extract a vector of all SQualityTopicInfo matching the given topic name. + * + * @param topic_name_ The topic name. + * @param quality_data_type_info_multi_map_ MultiMap { TopicName -> SQualityTopicInfo }. + * + * @return Vector of SQualityTopicInfo + **/ + std::vector GetQualityTopicInfoVec(const std::string& topic_name_, const std::multimap& quality_data_type_info_multi_map_) { - std::vector data_info_vec; + std::vector quality_topic_info_vec; - const auto data_info_range = data_info_multi_map_.equal_range(topic_name_); - for (auto data_info_range_it = data_info_range.first; data_info_range_it != data_info_range.second; ++data_info_range_it) + const auto topic_info_range = quality_data_type_info_multi_map_.equal_range(topic_name_); + for (auto topic_info_range_it = topic_info_range.first; topic_info_range_it != topic_info_range.second; ++topic_info_range_it) { - data_info_vec.push_back(data_info_range_it->second); + quality_topic_info_vec.push_back(topic_info_range_it->second); } - return data_info_vec; + return quality_topic_info_vec; } - std::vector GetServiceTypeInformation(const std::string& service_name_, const std::string& method_name_, std::multimap, eCAL::Util::SQualityServiceMethodInformation> service_info_map_) + /** + * @brief Extract a vector of all SQualityServiceInfo matching the given service name/method name. + * + * @param service_name_ The service name. + * @param method_name_ The method name. + * @param quality_service_info_multi_map_ MultiMap { -> SQualityServiceInfo }. + * + * @return Vector of SQualityServiceInfo + **/ + std::vector GetQualityServiceInfoVec(const std::string& service_name_, const std::string& method_name_, std::multimap, eCAL::Util::SQualityServiceInfo> quality_service_info_multi_map_) { - std::vector service_method_info_vec; + std::vector quality_service_info_vec; - const auto service_info_range = service_info_map_.equal_range(std::make_pair(service_name_, method_name_)); + const auto service_info_range = quality_service_info_multi_map_.equal_range(std::make_pair(service_name_, method_name_)); for (auto service_info_range_it = service_info_range.first; service_info_range_it != service_info_range.second; ++service_info_range_it) { - service_method_info_vec.push_back(service_info_range_it->second); + quality_service_info_vec.push_back(service_info_range_it->second); } - return service_method_info_vec; + return quality_service_info_vec; } - std::unordered_map GetQualifiedMap(const std::multimap& source_multi_map_) + /** + * @brief Reducing std::map<(TopicName, TopicID), SQualityTopicInfo> to + * std::map based on the quality + * + * @param source_map_ std::map<(TopicName, TopicID), SQualityTopicInfo>. + * + * @return std::map + **/ + std::map ReduceQualityTopicIdMap(const eCAL::QualityTopicIdMap& source_map_) { - std::unordered_map target_map; + std::map target_map; - for (const auto& source_pair : source_multi_map_) + for (const auto& source_pair : source_map_) { - const std::string& source_key = source_pair.first; - const eCAL::Util::SQualityDataTypeInformation& source_value = source_pair.second; + const auto& source_key = source_pair.first; + const auto& source_value = source_pair.second; - auto target_it = target_map.find(source_key); + auto target_it = target_map.find(source_key.topic_name); if (target_it != target_map.end()) { // key exists in target map @@ -78,7 +102,44 @@ namespace else { // key does not exist in target map, insert source pair - target_map.insert(source_pair); + target_map.insert(std::make_pair(source_key.topic_name, source_value)); + } + } + + return target_map; + } + + /** + * @brief Reducing std::map<(ServiceName, ServiceId, MethodName), SQualityServiceInfo> to + * std::map, SQualityServiceInfo> based on the quality + * + * @param source_map_ std::map<(ServiceName, ServiceId, MethodName), SQualityServiceInfo>. + * + * @return std::map, SQualityServiceInfo> + **/ + std::map, eCAL::Util::SQualityServiceInfo> ReduceQualityServiceIdMap(const eCAL::QualityServiceIdMap& source_map_) + { + std::map, eCAL::Util::SQualityServiceInfo> target_map; + + for (const auto& source_pair : source_map_) + { + const auto& source_key = source_pair.first; + const auto& source_value = source_pair.second; + + auto target_it = target_map.find(std::make_tuple(source_key.service_name, source_key.method_name)); + if (target_it != target_map.end()) + { + // key exists in target map + if (source_value.quality > target_it->second.quality) + { + // source quality is greater, overwrite + target_it->second = source_value; + } + } + else + { + // key does not exist in target map, insert source pair + target_map.insert(std::make_pair(std::make_tuple(source_key.service_name, source_key.method_name), source_pair.second)); } } @@ -226,131 +287,122 @@ namespace eCAL } #endif // ECAL_CORE_MONITORING - std::multimap GetPublisher() + std::multimap GetPublisher() { - std::multimap multi_map; + std::multimap multi_map; if (g_descgate() == nullptr) return multi_map; // insert publisher into target multimap for (const auto& topic : g_descgate()->GetPublisher()) { - multi_map.insert(std::pair(topic.first.topic_name, topic.second)); + multi_map.insert(std::pair(topic.first.topic_name, topic.second)); } return multi_map; } - std::vector GetPublisher(const std::string& topic_name_) + std::vector GetPublisher(const std::string& topic_name_) { - return ::GetTopicDataTypeInformation(topic_name_, GetPublisher()); + return ::GetQualityTopicInfoVec(topic_name_, GetPublisher()); } - std::multimap GetSubscriber() + std::multimap GetSubscriber() { - std::multimap multi_map; + std::multimap multi_map; if (g_descgate() == nullptr) return multi_map; // insert subscriber into target multimap for (const auto& topic : g_descgate()->GetSubscriber()) { - multi_map.insert(std::pair(topic.first.topic_name, topic.second)); + multi_map.insert(std::pair(topic.first.topic_name, topic.second)); } return multi_map; } - std::vector GetSubscriber(const std::string& topic_name_) + std::vector GetSubscriber(const std::string& topic_name_) { - return ::GetTopicDataTypeInformation(topic_name_, GetSubscriber()); + return ::GetQualityTopicInfoVec(topic_name_, GetSubscriber()); } - SDataTypeInformation GetHighestQualifiedDataTypeInformation(const std::vector& data_type_info_vec_) + SDataTypeInformation GetHighestQualityDataTypeInformation(const std::vector& quality_topic_info_vec_) { - SQualityDataTypeInformation quality_info; - for (const auto& info : data_type_info_vec_) + SQualityTopicInfo highest_quality_topic_info; + for (const auto& info : quality_topic_info_vec_) { - if (info.quality > quality_info.quality) + if (info.quality > highest_quality_topic_info.quality) { - quality_info = info; + highest_quality_topic_info = info; } } - return quality_info.info; + return highest_quality_topic_info.info; } - ECAL_API std::multimap, SQualityServiceMethodInformation> GetServices() + std::multimap, SQualityServiceInfo> GetServices() { - std::multimap, SQualityServiceMethodInformation> multi_map; + std::multimap, SQualityServiceInfo> multi_map; if (g_descgate() == nullptr) return multi_map; // insert services into target multimap for (const auto& service : g_descgate()->GetServices()) { - multi_map.insert(std::pair, SQualityServiceMethodInformation>(std::make_tuple(service.first.service_name, service.first.method_name), service.second)); + multi_map.insert(std::pair, SQualityServiceInfo>(std::make_tuple(service.first.service_name, service.first.method_name), service.second)); } return multi_map; } - ECAL_API std::multimap, SQualityServiceMethodInformation> GetClients() + std::multimap, SQualityServiceInfo> GetClients() { - std::multimap, SQualityServiceMethodInformation> multi_map; + std::multimap, SQualityServiceInfo> multi_map; if (g_descgate() == nullptr) return multi_map; // insert clients into target multimap for (const auto& client : g_descgate()->GetClients()) { - multi_map.insert(std::pair, SQualityServiceMethodInformation>(std::make_tuple(client.first.service_name, client.first.method_name), client.second)); + multi_map.insert(std::pair, SQualityServiceInfo>(std::make_tuple(client.first.service_name, client.first.method_name), client.second)); } + return multi_map; } - SServiceMethodInformation GetHighestQualifiedServiceMethodInformation(const std::vector& service_method_info_vec_) + SServiceMethodInformation GetHighestQualityServiceMethodInformation(const std::vector& quality_service_info_vec_) { - SQualityServiceMethodInformation quality_info; - for (const auto& info : service_method_info_vec_) + SQualityServiceInfo highest_quality_service_info; + for (const auto& info : quality_service_info_vec_) { - if (info.quality > quality_info.quality) + if (info.quality > highest_quality_service_info.quality) { - quality_info = info; + highest_quality_service_info = info; } } - return quality_info.info; + return highest_quality_service_info.info; } - void GetTopics(std::unordered_map& data_type_info_map_) + void GetTopics(std::map& data_type_info_map_) { data_type_info_map_.clear(); - std::unordered_map qualified_data_type_info_map; - GetTopics(qualified_data_type_info_map); + std::map quality_data_type_info_map; + GetTopics(quality_data_type_info_map); // transform into target map - for (const auto& qualified_data_type_info : qualified_data_type_info_map) + for (const auto& quality_data_type_info : quality_data_type_info_map) { - data_type_info_map_.insert(std::pair(qualified_data_type_info.first, qualified_data_type_info.second.info)); + data_type_info_map_.insert(std::pair(quality_data_type_info.first, quality_data_type_info.second.info)); } } - void GetTopics(std::unordered_map& qualified_data_type_info_map_) + void GetTopics(std::map& quality_topic_info_map_) { - qualified_data_type_info_map_.clear(); + quality_topic_info_map_.clear(); if (g_descgate() == nullptr) return; - std::multimap merged_pub_sub_map; + QualityTopicIdMap pub_sub_map = g_descgate()->GetPublisher(); + QualityTopicIdMap sub_map = g_descgate()->GetSubscriber(); + pub_sub_map.insert(sub_map.begin(), sub_map.end()); - // insert publisher - for (const auto& topic : g_descgate()->GetPublisher()) - { - merged_pub_sub_map.insert(std::pair(topic.first.topic_name, topic.second)); - } - - // insert subscriber - for (const auto& topic : g_descgate()->GetSubscriber()) - { - merged_pub_sub_map.insert(std::pair(topic.first.topic_name, topic.second)); - } - - // transform into a map with the highest qualified data type information - qualified_data_type_info_map_ = GetQualifiedMap(merged_pub_sub_map); + // transform into a map with the highest quality data type information + quality_topic_info_map_ = ReduceQualityTopicIdMap(pub_sub_map); } void GetTopicNames(std::vector& topic_names_) @@ -376,37 +428,63 @@ namespace eCAL topic_names_ = std::vector(set.begin(), set.end()); } - bool GetTopicDataTypeInformation(const std::string& topic_name_, SDataTypeInformation& topic_info_) + bool GetTopicDataTypeInformation(const std::string& topic_name_, SDataTypeInformation& data_type_info_) { auto info_vec = GetPublisher(topic_name_); const auto sub_info_vec = GetSubscriber(topic_name_); info_vec.insert(info_vec.end(), sub_info_vec.begin(), sub_info_vec.end()); - topic_info_ = GetHighestQualifiedDataTypeInformation(info_vec); + data_type_info_ = GetHighestQualityDataTypeInformation(info_vec); return !info_vec.empty(); } - void GetServices(std::map, SServiceMethodInformation>& service_info_map_) + void GetServices(std::map, SServiceMethodInformation>& service_method_info_map_) { - // TODO: Implement this with comparison + service_method_info_map_.clear(); + + std::map, SQualityServiceInfo> quality_service_method_info_map; + GetServices(quality_service_method_info_map); + + // transform into target map + for (const auto& quality_service_method_info : quality_service_method_info_map) + { + service_method_info_map_.insert(std::pair, SServiceMethodInformation>(quality_service_method_info.first, quality_service_method_info.second.info)); + } } - void GetServices(std::map, SQualityServiceMethodInformation>& qualified_service_info_map_) + void GetServices(std::map, SQualityServiceInfo>& quality_service_info_map_) { - // TODO: Implement this + quality_service_info_map_.clear(); + if (g_descgate() == nullptr) return; + + // transform into a map with the highest quality service method information + quality_service_info_map_ = ReduceQualityServiceIdMap(g_descgate()->GetServices()); } void GetServiceMethodNames(std::vector>& service_method_names_) { - // TODO: Implement this with comparison + service_method_names_.clear(); + + // get services multi map + auto multi_map = GetServices(); + + // filter out unique service names into a set + std::set> set; + for (const auto& service : multi_map) + { + set.insert(service.first); + } + + // transform set into target vector + service_method_names_ = std::vector>(set.begin(), set.end()); } bool GetServiceTypeNames(const std::string& service_name_, const std::string& method_name_, std::string& req_type_, std::string& resp_type_) { - std::vector service_method_info_vec = GetServiceTypeInformation(service_name_, method_name_, GetServices()); + std::vector service_method_info_vec = GetQualityServiceInfoVec(service_name_, method_name_, GetServices()); - SServiceMethodInformation service_method_info = GetHighestQualifiedServiceMethodInformation(service_method_info_vec); + SServiceMethodInformation service_method_info = GetHighestQualityServiceMethodInformation(service_method_info_vec); req_type_ = service_method_info.request_type.name; resp_type_ = service_method_info.response_type.name; @@ -415,35 +493,61 @@ namespace eCAL bool GetServiceDescription(const std::string& service_name_, const std::string& method_name_, std::string& req_desc_, std::string& resp_desc_) { - std::vector service_method_info_vec = GetServiceTypeInformation(service_name_, method_name_, GetServices()); + std::vector service_method_info_vec = GetQualityServiceInfoVec(service_name_, method_name_, GetServices()); - SServiceMethodInformation service_method_info = GetHighestQualifiedServiceMethodInformation(service_method_info_vec); + SServiceMethodInformation service_method_info = GetHighestQualityServiceMethodInformation(service_method_info_vec); req_desc_ = service_method_info.request_type.descriptor; resp_desc_ = service_method_info.response_type.descriptor; return !service_method_info_vec.empty(); } - void GetClients(std::map, SServiceMethodInformation>& client_info_map_) + void GetClients(std::map, SServiceMethodInformation>& client_method_info_map_) { - // TODO: Implement this with comparison + client_method_info_map_.clear(); + + std::map, SQualityServiceInfo> quality_client_method_info_map_; + GetClients(quality_client_method_info_map_); + + // transform into target map + for (const auto& quality_client_method_info : quality_client_method_info_map_) + { + client_method_info_map_.insert(std::pair, SServiceMethodInformation>(quality_client_method_info.first, quality_client_method_info.second.info)); + } } - void GetClients(std::map, SQualityServiceMethodInformation>& qualified_client_info_map_) + void GetClients(std::map, SQualityServiceInfo>& quality_client_method_info_map_) { - // TODO: Implement this + quality_client_method_info_map_.clear(); + if (g_descgate() == nullptr) return; + + // transform into a map with the highest quality service method information + quality_client_method_info_map_ = ReduceQualityServiceIdMap(g_descgate()->GetClients()); } void GetClientMethodNames(std::vector>& client_method_names_) { - // TODO: Implement this with comparison + client_method_names_.clear(); + + // get services multi map + auto multi_map = GetClients(); + + // filter out unique service names into a set + std::set> set; + for (const auto& service : multi_map) + { + set.insert(service.first); + } + + // transform set into target vector + client_method_names_ = std::vector>(set.begin(), set.end()); } bool GetClientTypeNames(const std::string& client_name_, const std::string& method_name_, std::string& req_type_, std::string& resp_type_) { - std::vector service_method_info_vec = GetServiceTypeInformation(client_name_, method_name_, GetClients()); + std::vector service_method_info_vec = GetQualityServiceInfoVec(client_name_, method_name_, GetClients()); - SServiceMethodInformation service_method_info = GetHighestQualifiedServiceMethodInformation(service_method_info_vec); + SServiceMethodInformation service_method_info = GetHighestQualityServiceMethodInformation(service_method_info_vec); req_type_ = service_method_info.request_type.name; resp_type_ = service_method_info.response_type.name; @@ -452,9 +556,9 @@ namespace eCAL bool GetClientDescription(const std::string& client_name_, const std::string& method_name_, std::string& req_desc_, std::string& resp_desc_) { - std::vector service_method_info_vec = GetServiceTypeInformation(client_name_, method_name_, GetClients()); + std::vector service_method_info_vec = GetQualityServiceInfoVec(client_name_, method_name_, GetClients()); - SServiceMethodInformation service_method_info = GetHighestQualifiedServiceMethodInformation(service_method_info_vec); + SServiceMethodInformation service_method_info = GetHighestQualityServiceMethodInformation(service_method_info_vec); req_desc_ = service_method_info.request_type.descriptor; resp_desc_ = service_method_info.response_type.descriptor; diff --git a/ecal/tests/cpp/util_test/src/util_getclients.cpp b/ecal/tests/cpp/util_test/src/util_getclients.cpp index 7b5230a56d..922e465e66 100644 --- a/ecal/tests/cpp/util_test/src/util_getclients.cpp +++ b/ecal/tests/cpp/util_test/src/util_getclients.cpp @@ -134,15 +134,7 @@ TEST(core_cpp_util, GetClients) // destroy client 1 client1.Destroy(); - // check attributes (client 1 is still in the map) - eCAL::Util::GetClientTypeNames("foo::service", "foo::method", req_type, resp_type); - EXPECT_EQ(req_type, "foo::req_type1"); - EXPECT_EQ(resp_type, "foo::resp_type1"); - - // let's wait a registration cylce long - eCAL::Process::SleepMS(CMN_REGISTRATION_REFRESH); - - // check attributes (client 1 should be replaced by client 2 now) + // check attributes (client 1 should be replaced by client 2 immediately) eCAL::Util::GetClientTypeNames("foo::service", "foo::method", req_type, resp_type); EXPECT_EQ(req_type, "foo::req_type2"); EXPECT_EQ(resp_type, "foo::resp_type2"); diff --git a/ecal/tests/cpp/util_test/src/util_gettopics.cpp b/ecal/tests/cpp/util_test/src/util_gettopics.cpp index f31efadbac..c8d739e03d 100644 --- a/ecal/tests/cpp/util_test/src/util_gettopics.cpp +++ b/ecal/tests/cpp/util_test/src/util_gettopics.cpp @@ -19,7 +19,7 @@ #include -#include +#include #include #include @@ -33,7 +33,7 @@ TEST(core_cpp_util, GetTopics) // initialize eCAL API eCAL::Initialize(0, nullptr, "pubsub_gettopics"); - std::unordered_map topic_info_map; + std::map topic_info_map; // create and check a few pub/sub entities { @@ -146,7 +146,7 @@ TEST(core_cpp_util, GetTopicsParallel) auto get_topics_from_ecal = [&]() { size_t found_topics = 0; std::vector tmp_topic_names; - std::unordered_map topics; + std::map topics; do { eCAL::Util::GetTopicNames(tmp_topic_names); eCAL::Util::GetTopics(topics); @@ -179,7 +179,7 @@ TEST(core_cpp_util, GetTopicsParallel) } std::vector final_topic_names; - std::unordered_map final_topics; + std::map final_topics; eCAL::Util::GetTopicNames(final_topic_names); eCAL::Util::GetTopics(final_topics); From f4b789c6a1d25f2cf60db83dedc56631cd8f041a Mon Sep 17 00:00:00 2001 From: rex-schilasky <49162693+rex-schilasky@users.noreply.github.com> Date: Sun, 14 Apr 2024 22:58:59 +0200 Subject: [PATCH 08/27] clang-tidy and minor type fix --- ecal/core/include/ecal/ecal_util.h | 52 +++++++++---------- ecal/core/src/ecal_descgate.cpp | 3 -- ecal/core/src/ecal_descgate.h | 9 +++- .../src/monitoring_get_topics.cpp | 2 +- 4 files changed, 35 insertions(+), 31 deletions(-) diff --git a/ecal/core/include/ecal/ecal_util.h b/ecal/core/include/ecal/ecal_util.h index 7eabde9340..f7d5136f01 100644 --- a/ecal/core/include/ecal/ecal_util.h +++ b/ecal/core/include/ecal/ecal_util.h @@ -39,7 +39,7 @@ namespace eCAL namespace Util { // enumeration of quality bits used for detecting how good a data information is - enum class DescQualityFlags : int + enum class DescQualityFlags : std::uint8_t { NO_QUALITY = 0, //!< Special value for initialization DESCRIPTION_AVAILABLE = 0x1 << 3, //!< Having a type descriptor available @@ -47,7 +47,7 @@ namespace eCAL TYPENAME_AVAILABLE = 0x1 << 1, //!< Having a type name available INFO_COMES_FROM_PRODUCER = 0x1 << 0 //!< Info is coming from the producer (like a publisher, service) }; - inline DescQualityFlags& operator|= (DescQualityFlags& a, DescQualityFlags b) { return reinterpret_cast(reinterpret_cast::type&>(a) |= static_cast::type>(b)); } + inline DescQualityFlags& operator|= (DescQualityFlags& a, DescQualityFlags b) { return reinterpret_cast(reinterpret_cast&>(a) |= static_cast>(b)); } struct SQualityTopicInfo { @@ -150,7 +150,7 @@ namespace eCAL /** * @brief Get complete snapshot of data type information with quality and topic id for all known publisher. * - * @return MultiMap containing the qualified datatype information and the topic id's. + * @return MultiMap containing the quality datatype information and the topic id's. **/ ECAL_API std::multimap GetPublisher(); @@ -159,14 +159,14 @@ namespace eCAL * * @param topic_name_ Topic name. * - * @return Vector containing the qualified datatype information for this publisher. + * @return Vector containing the quality datatype information for this publisher. **/ ECAL_API std::vector GetPublisher(const std::string& topic_name_); /** * @brief Get complete snapshot of data type information with quality and topic id for all known subscriber. * - * @return MultiMap containing the qualified datatype information and the topic id's. + * @return MultiMap containing the quality datatype information and the topic id's. **/ ECAL_API std::multimap GetSubscriber(); @@ -175,39 +175,39 @@ namespace eCAL * * @param topic_name_ Topic name. * - * @return Vector containing the qualified datatype information for this subscriber. + * @return Vector containing the quality datatype information for this subscriber. **/ ECAL_API std::vector GetSubscriber(const std::string& topic_name_); /** - * @brief Get highest qualified data type information out of a vector of qualified data type information. + * @brief Get highest quality data type information out of a vector of quality data type information. * - * @param data_type_info_vec_ Vector of qualified data type information + * @param data_type_info_vec_ Vector of quality data type information * - * @return Highest qualified data type information. + * @return Highest quality data type information. **/ ECAL_API SDataTypeInformation GetHighestQualityDataTypeInformation(const std::vector& data_type_info_vec_); /** * @brief Get complete snapshot of service method information with quality and service id for all known services. * - * @return MultiMap containing the qualified datatype information and the service id's. + * @return MultiMap containing the quality datatype information and the service id's. **/ ECAL_API std::multimap, SQualityServiceInfo> GetServices(); /** * @brief Get complete snapshot of service method information with quality and client id for all known clients. * - * @return MultiMap containing the qualified datatype information and the client id's. + * @return MultiMap containing the quality datatype information and the client id's. **/ ECAL_API std::multimap, SQualityServiceInfo> GetClients(); /** - * @brief Get highest qualified service method type information out of a vector of qualified service method information. + * @brief Get highest quality service method type information out of a vector of quality service method information. * - * @param service_method_info_vec_ Vector of qualified service method information + * @param service_method_info_vec_ Vector of quality service method information * - * @return Highest qualified service method information. + * @return Highest quality service method information. **/ ECAL_API SServiceMethodInformation GetHighestQualityServiceMethodInformation(const std::vector& service_method_info_vec_); @@ -220,12 +220,12 @@ namespace eCAL ECAL_API void GetTopics(std::map& data_type_info_map_); /** - * @brief Get complete qualified topic map. + * @brief Get complete quality topic map. * - * @param qualfied_data_type_info_map_ Map to store the qualified datatype information. - * Map { TopicName -> SQualityDataTypeInformation } mapping of all currently known publisher/subscriber. + * @param quality_data_type_info_map_ Map to store the quality datatype information. + * Map { TopicName -> SQualityDataTypeInformation } mapping of all currently known publisher/subscriber. **/ - ECAL_API void GetTopics(std::map& qualfied_data_type_info_map_); + ECAL_API void GetTopics(std::map& quality_data_type_info_map_); /** * @brief Get all topic names. @@ -253,12 +253,12 @@ namespace eCAL ECAL_API void GetServices(std::map, SServiceMethodInformation>& service_info_map_); /** - * @brief Get complete qualified service map. + * @brief Get complete quality service map. * - * @param qualified_service_info_map_ Map to store the qualified service/method descriptions. - * Map { (ServiceName, MethodName) -> SQualityServiceMethodInformation } mapping of all currently known services. + * @param quality_service_info_map_ Map to store the quality service/method descriptions. + * Map { (ServiceName, MethodName) -> SQualityServiceMethodInformation } mapping of all currently known services. **/ - ECAL_API void GetServices(std::map, SQualityServiceInfo>& qualified_service_info_map_); + ECAL_API void GetServices(std::map, SQualityServiceInfo>& quality_service_info_map_); /** * @brief Get all service/method names. @@ -300,12 +300,12 @@ namespace eCAL ECAL_API void GetClients(std::map, SServiceMethodInformation>& client_info_map_); /** - * @brief Get complete qualified client map. + * @brief Get complete quality client map. * - * @param qualified_client_info_map_ Map to store the qualified client/method descriptions. - * Map { (ClientName, MethodName) -> SQualityServiceMethodInformation } mapping of all currently known clients. + * @param quality_client_info_map_ Map to store the quality client/method descriptions. + * Map { (ClientName, MethodName) -> SQualityServiceMethodInformation } mapping of all currently known clients. **/ - ECAL_API void GetClients(std::map, SQualityServiceInfo>& qualified_client_info_map_); + ECAL_API void GetClients(std::map, SQualityServiceInfo>& quality_client_info_map_); /** * @brief Get all client/method names. diff --git a/ecal/core/src/ecal_descgate.cpp b/ecal/core/src/ecal_descgate.cpp index a54ac96f77..44770dcebd 100644 --- a/ecal/core/src/ecal_descgate.cpp +++ b/ecal/core/src/ecal_descgate.cpp @@ -225,9 +225,6 @@ namespace eCAL const std::unique_lock lock(topic_info_map_.mtx); topic_info_map_.map->remove_deprecated(); - - const auto topic_info_it = topic_info_map_.map->find(topic_info_key); - (*topic_info_map_.map)[topic_info_key] = topic_quality_info; } diff --git a/ecal/core/src/ecal_descgate.h b/ecal/core/src/ecal_descgate.h index a6475e3585..dcb18de442 100644 --- a/ecal/core/src/ecal_descgate.h +++ b/ecal/core/src/ecal_descgate.h @@ -71,7 +71,6 @@ namespace eCAL class CDescGate { public: - CDescGate(); ~CDescGate(); @@ -84,6 +83,14 @@ namespace eCAL QualityServiceIdMap GetServices(); QualityServiceIdMap GetClients(); + // delete copy constructor and copy assignment operator + CDescGate(const CDescGate&) = delete; + CDescGate& operator=(const CDescGate&) = delete; + + // delete move constructor and move assignment operator + CDescGate(CDescGate&&) = delete; + CDescGate& operator=(CDescGate&&) = delete; + protected: using QualityTopicIdExpMap = eCAL::Util::CExpMap; struct SQualityTopicIdMap diff --git a/ecal/samples/cpp/monitoring/monitoring_get_topics/src/monitoring_get_topics.cpp b/ecal/samples/cpp/monitoring/monitoring_get_topics/src/monitoring_get_topics.cpp index 7e7c5acdcf..692562dd15 100644 --- a/ecal/samples/cpp/monitoring/monitoring_get_topics/src/monitoring_get_topics.cpp +++ b/ecal/samples/cpp/monitoring/monitoring_get_topics/src/monitoring_get_topics.cpp @@ -37,7 +37,7 @@ int main(int argc, char **argv) { // GetTopics { - std::unordered_map topic_info_map; + std::map topic_info_map; start_time = std::chrono::steady_clock::now(); for (run = 0; run < runs; ++run) From 45a7c078dae134ccc010295d6f418404b7a8ea9e Mon Sep 17 00:00:00 2001 From: rex-schilasky <49162693+rex-schilasky@users.noreply.github.com> Date: Sun, 14 Apr 2024 23:34:26 +0200 Subject: [PATCH 09/27] argument name fixes --- ecal/core/include/ecal/ecal_util.h | 38 +++++++++++++++--------------- ecal/core/src/ecal_util.cpp | 6 ++--- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/ecal/core/include/ecal/ecal_util.h b/ecal/core/include/ecal/ecal_util.h index f7d5136f01..43189c15a5 100644 --- a/ecal/core/include/ecal/ecal_util.h +++ b/ecal/core/include/ecal/ecal_util.h @@ -182,11 +182,11 @@ namespace eCAL /** * @brief Get highest quality data type information out of a vector of quality data type information. * - * @param data_type_info_vec_ Vector of quality data type information + * @param quality_topic_info_vec_ Vector of quality data type information * * @return Highest quality data type information. **/ - ECAL_API SDataTypeInformation GetHighestQualityDataTypeInformation(const std::vector& data_type_info_vec_); + ECAL_API SDataTypeInformation GetHighestQualityDataTypeInformation(const std::vector& quality_topic_info_vec_); /** * @brief Get complete snapshot of service method information with quality and service id for all known services. @@ -205,27 +205,27 @@ namespace eCAL /** * @brief Get highest quality service method type information out of a vector of quality service method information. * - * @param service_method_info_vec_ Vector of quality service method information + * @param quality_service_info_vec_ Vector of quality service method information * * @return Highest quality service method information. **/ - ECAL_API SServiceMethodInformation GetHighestQualityServiceMethodInformation(const std::vector& service_method_info_vec_); + ECAL_API SServiceMethodInformation GetHighestQualityServiceMethodInformation(const std::vector& quality_service_info_vec_); /** * @brief Get complete topic map. * - * @param topic_info_map_ Map to store the datatype information. - * Map { TopicName -> SDataTypeInformation } mapping of all currently known publisher/subscriber. + * @param data_type_info_map_ Map to store the datatype information. + * Map { TopicName -> SDataTypeInformation } mapping of all currently known publisher/subscriber. **/ ECAL_API void GetTopics(std::map& data_type_info_map_); /** * @brief Get complete quality topic map. * - * @param quality_data_type_info_map_ Map to store the quality datatype information. - * Map { TopicName -> SQualityDataTypeInformation } mapping of all currently known publisher/subscriber. + * @param quality_topic_info_map_ Map to store the quality datatype information. + * Map { TopicName -> SQualityDataTypeInformation } mapping of all currently known publisher/subscriber. **/ - ECAL_API void GetTopics(std::map& quality_data_type_info_map_); + ECAL_API void GetTopics(std::map& quality_topic_info_map_); /** * @brief Get all topic names. @@ -237,26 +237,26 @@ namespace eCAL /** * @brief Gets description of the specified topic. * - * @param topic_name_ Topic name. - * @param topic_info_ SDataTypeInformation to be filled by this function. + * @param topic_name_ Topic name. + * @param data_type_info_ SDataTypeInformation to be filled by this function. * * @return True if TopicInformation for specified topic could be retrieved, false otherwise. **/ - ECAL_API bool GetTopicDataTypeInformation(const std::string& topic_name_, SDataTypeInformation& topic_info_); + ECAL_API bool GetTopicDataTypeInformation(const std::string& topic_name_, SDataTypeInformation& data_type_info_); /** * @brief Get complete service map. * - * @param service_info_map_ Map to store the service/method descriptions. - * Map { (ServiceName, MethodName) -> SServiceMethodInformation } mapping of all currently known services. + * @param service_method_info_map_ Map to store the service/method descriptions. + * Map { (ServiceName, MethodName) -> SServiceMethodInformation } mapping of all currently known services. **/ - ECAL_API void GetServices(std::map, SServiceMethodInformation>& service_info_map_); + ECAL_API void GetServices(std::map, SServiceMethodInformation>& service_method_info_map_); /** * @brief Get complete quality service map. * * @param quality_service_info_map_ Map to store the quality service/method descriptions. - * Map { (ServiceName, MethodName) -> SQualityServiceMethodInformation } mapping of all currently known services. + * Map { (ServiceName, MethodName) -> SQualityServiceMethodInformation } mapping of all currently known services. **/ ECAL_API void GetServices(std::map, SQualityServiceInfo>& quality_service_info_map_); @@ -294,10 +294,10 @@ namespace eCAL /** * @brief Get complete client map. * - * @param client_info_map_ Map to store the client/method descriptions. - * Map { (ClientName, MethodName) -> SServiceMethodInformation } mapping of all currently known clients. + * @param client_method_info_map_ Map to store the client/method descriptions. + * Map { (ClientName, MethodName) -> SServiceMethodInformation } mapping of all currently known clients. **/ - ECAL_API void GetClients(std::map, SServiceMethodInformation>& client_info_map_); + ECAL_API void GetClients(std::map, SServiceMethodInformation>& client_method_info_map_); /** * @brief Get complete quality client map. diff --git a/ecal/core/src/ecal_util.cpp b/ecal/core/src/ecal_util.cpp index 25d155150f..2f3f0c43f1 100644 --- a/ecal/core/src/ecal_util.cpp +++ b/ecal/core/src/ecal_util.cpp @@ -516,13 +516,13 @@ namespace eCAL } } - void GetClients(std::map, SQualityServiceInfo>& quality_client_method_info_map_) + void GetClients(std::map, SQualityServiceInfo>& quality_client_info_map_) { - quality_client_method_info_map_.clear(); + quality_client_info_map_.clear(); if (g_descgate() == nullptr) return; // transform into a map with the highest quality service method information - quality_client_method_info_map_ = ReduceQualityServiceIdMap(g_descgate()->GetClients()); + quality_client_info_map_ = ReduceQualityServiceIdMap(g_descgate()->GetClients()); } void GetClientMethodNames(std::vector>& client_method_names_) From a46fc88101d52ac458fe22cf834fd48ff143c933 Mon Sep 17 00:00:00 2001 From: rex-schilasky <49162693+rex-schilasky@users.noreply.github.com> Date: Mon, 15 Apr 2024 13:53:06 +0200 Subject: [PATCH 10/27] service data type info quality split for request and response util test, getservices, getclients started to refactor --- ecal/core/include/ecal/ecal_util.h | 3 +- ecal/core/src/ecal_descgate.cpp | 51 ++---- ecal/core/src/ecal_descgate.h | 5 +- ecal/core/src/ecal_util.cpp | 16 +- .../cpp/util_test/src/util_getclients.cpp | 130 +++++++++++--- .../cpp/util_test/src/util_getservices.cpp | 164 +++++++++++++----- .../cpp/util_test/src/util_gettopics.cpp | 9 +- 7 files changed, 256 insertions(+), 122 deletions(-) diff --git a/ecal/core/include/ecal/ecal_util.h b/ecal/core/include/ecal/ecal_util.h index 43189c15a5..9cec991cf8 100644 --- a/ecal/core/include/ecal/ecal_util.h +++ b/ecal/core/include/ecal/ecal_util.h @@ -60,7 +60,8 @@ namespace eCAL { std::string id; SServiceMethodInformation info; - DescQualityFlags quality = DescQualityFlags::NO_QUALITY; + DescQualityFlags request_quality = DescQualityFlags::NO_QUALITY; + DescQualityFlags response_quality = DescQualityFlags::NO_QUALITY; }; /** diff --git a/ecal/core/src/ecal_descgate.cpp b/ecal/core/src/ecal_descgate.cpp index 44770dcebd..b4ded553ac 100644 --- a/ecal/core/src/ecal_descgate.cpp +++ b/ecal/core/src/ecal_descgate.cpp @@ -29,41 +29,16 @@ namespace { - eCAL::Util::DescQualityFlags GetClientQuality(const eCAL::SDataTypeInformation& request_info_, const eCAL::SDataTypeInformation& response_info_) + eCAL::Util::DescQualityFlags GetDataTypeInfoQuality(const eCAL::SDataTypeInformation& data_type_info_, bool is_producer_) { eCAL::Util::DescQualityFlags quality = eCAL::Util::DescQualityFlags::NO_QUALITY; - if (!(request_info_.name.empty() && response_info_.name.empty())) + if (!data_type_info_.name.empty()) quality |= eCAL::Util::DescQualityFlags::TYPENAME_AVAILABLE; - if (!(request_info_.encoding.empty() && response_info_.encoding.empty())) + if (!data_type_info_.encoding.empty()) quality |= eCAL::Util::DescQualityFlags::ENCODING_AVAILABLE; - if (!(request_info_.descriptor.empty() && response_info_.descriptor.empty())) + if (!data_type_info_.descriptor.empty()) quality |= eCAL::Util::DescQualityFlags::DESCRIPTION_AVAILABLE; - return quality; - } - - eCAL::Util::DescQualityFlags GetServiceQuality(const eCAL::SDataTypeInformation& request_info_, const eCAL::SDataTypeInformation& response_info_) - { - eCAL::Util::DescQualityFlags quality = GetClientQuality(request_info_, response_info_); - quality |= eCAL::Util::DescQualityFlags::INFO_COMES_FROM_PRODUCER; - return quality; - } - - eCAL::Util::DescQualityFlags GetSubscriberQuality(const eCAL::SDataTypeInformation& topic_info_) - { - eCAL::Util::DescQualityFlags quality = eCAL::Util::DescQualityFlags::NO_QUALITY; - if (!topic_info_.name.empty()) - quality |= eCAL::Util::DescQualityFlags::TYPENAME_AVAILABLE; - if (!topic_info_.encoding.empty()) - quality |= eCAL::Util::DescQualityFlags::ENCODING_AVAILABLE; - if (!topic_info_.descriptor.empty()) - quality |= eCAL::Util::DescQualityFlags::DESCRIPTION_AVAILABLE; - return quality; - } - - eCAL::Util::DescQualityFlags GetPublisherQuality(const eCAL::SDataTypeInformation& topic_info_) - { - eCAL::Util::DescQualityFlags quality = GetSubscriberQuality(topic_info_); - quality |= eCAL::Util::DescQualityFlags::INFO_COMES_FROM_PRODUCER; + if(is_producer_) quality |= eCAL::Util::DescQualityFlags::INFO_COMES_FROM_PRODUCER; return quality; } } @@ -166,7 +141,7 @@ namespace eCAL response_type.name = method.resp_type; response_type.descriptor = method.resp_desc; - ApplyServiceDescription(m_service_info_map, sample_.service.sname, sample_.service.sid, method.mname, request_type, response_type, GetServiceQuality(request_type, response_type)); + ApplyServiceDescription(m_service_info_map, sample_.service.sname, sample_.service.sid, method.mname, request_type, response_type, GetDataTypeInfoQuality(request_type, true), GetDataTypeInfoQuality(response_type, true)); } } break; @@ -184,20 +159,20 @@ namespace eCAL response_type.name = method.resp_type; response_type.descriptor = method.resp_desc; - ApplyServiceDescription(m_client_info_map, sample_.client.sname, sample_.client.sid, method.mname, request_type, response_type, GetClientQuality(request_type, response_type)); + ApplyServiceDescription(m_client_info_map, sample_.client.sname, sample_.client.sid, method.mname, request_type, response_type, GetDataTypeInfoQuality(request_type, false), GetDataTypeInfoQuality(response_type, false)); } break; case bct_unreg_client: RemServiceDescription(m_client_info_map, sample_.client.sname, sample_.client.sid); break; case bct_reg_publisher: - ApplyTopicDescription(m_publisher_info_map, sample_.topic.tname, sample_.topic.tid, sample_.topic.tdatatype, GetPublisherQuality(sample_.topic.tdatatype)); + ApplyTopicDescription(m_publisher_info_map, sample_.topic.tname, sample_.topic.tid, sample_.topic.tdatatype, GetDataTypeInfoQuality(sample_.topic.tdatatype, true)); break; case bct_unreg_publisher: RemTopicDescription(m_publisher_info_map, sample_.topic.tname, sample_.topic.tid); break; case bct_reg_subscriber: - ApplyTopicDescription(m_subscriber_info_map, sample_.topic.tname, sample_.topic.tid, sample_.topic.tdatatype, GetSubscriberQuality(sample_.topic.tdatatype)); + ApplyTopicDescription(m_subscriber_info_map, sample_.topic.tname, sample_.topic.tid, sample_.topic.tdatatype, GetDataTypeInfoQuality(sample_.topic.tdatatype, false)); break; case bct_unreg_subscriber: RemTopicDescription(m_subscriber_info_map, sample_.topic.tname, sample_.topic.tid); @@ -214,7 +189,7 @@ namespace eCAL const std::string& topic_name_, const std::string& topic_id_, const SDataTypeInformation& topic_info_, - Util::DescQualityFlags topic_quality_) + const Util::DescQualityFlags topic_quality_) { const auto topic_info_key = STopicIdKey{ topic_name_, topic_id_ }; @@ -241,7 +216,8 @@ namespace eCAL const std::string& method_name_, const SDataTypeInformation& request_type_information_, const SDataTypeInformation& response_type_information_, - const Util::DescQualityFlags service_quality_) + const Util::DescQualityFlags request_type_quality_, + const Util::DescQualityFlags response_type_quality_) { const auto service_method_info_key = SServiceIdKey{ service_name_, service_id_, method_name_ }; @@ -249,7 +225,8 @@ namespace eCAL service_quality_info.id = service_id_; service_quality_info.info.request_type = request_type_information_; service_quality_info.info.response_type = response_type_information_; - service_quality_info.quality = service_quality_; + service_quality_info.request_quality = request_type_quality_; + service_quality_info.response_quality = response_type_quality_; const std::lock_guard lock(service_method_info_map_.mtx); service_method_info_map_.map->remove_deprecated(); diff --git a/ecal/core/src/ecal_descgate.h b/ecal/core/src/ecal_descgate.h index dcb18de442..6ae6de2316 100644 --- a/ecal/core/src/ecal_descgate.h +++ b/ecal/core/src/ecal_descgate.h @@ -128,7 +128,7 @@ namespace eCAL const std::string& topic_name_, const std::string& topic_id_, const SDataTypeInformation& topic_info_, - Util::DescQualityFlags topic_quality_); + const Util::DescQualityFlags topic_quality_); void RemTopicDescription(SQualityTopicIdMap& topic_info_map_, const std::string& topic_name_, @@ -140,7 +140,8 @@ namespace eCAL const std::string& method_name_, const SDataTypeInformation& request_type_information_, const SDataTypeInformation& response_type_information_, - Util::DescQualityFlags service_quality_); + const Util::DescQualityFlags request_type_quality_, + const Util::DescQualityFlags response_type_quality_); void RemServiceDescription(SQualityServiceIdMap& service_method_info_map_, const std::string& service_name_, diff --git a/ecal/core/src/ecal_util.cpp b/ecal/core/src/ecal_util.cpp index 2f3f0c43f1..96ce442663 100644 --- a/ecal/core/src/ecal_util.cpp +++ b/ecal/core/src/ecal_util.cpp @@ -130,7 +130,8 @@ namespace if (target_it != target_map.end()) { // key exists in target map - if (source_value.quality > target_it->second.quality) + if ( (source_value.request_quality > target_it->second.request_quality) + || (source_value.response_quality > target_it->second.response_quality)) { // source quality is greater, overwrite target_it->second = source_value; @@ -370,7 +371,8 @@ namespace eCAL SQualityServiceInfo highest_quality_service_info; for (const auto& info : quality_service_info_vec_) { - if (info.quality > highest_quality_service_info.quality) + if ( (info.request_quality > highest_quality_service_info.request_quality) + || (info.response_quality > highest_quality_service_info.response_quality)) { highest_quality_service_info = info; } @@ -484,7 +486,7 @@ namespace eCAL { std::vector service_method_info_vec = GetQualityServiceInfoVec(service_name_, method_name_, GetServices()); - SServiceMethodInformation service_method_info = GetHighestQualityServiceMethodInformation(service_method_info_vec); + const SServiceMethodInformation service_method_info = GetHighestQualityServiceMethodInformation(service_method_info_vec); req_type_ = service_method_info.request_type.name; resp_type_ = service_method_info.response_type.name; @@ -495,8 +497,8 @@ namespace eCAL { std::vector service_method_info_vec = GetQualityServiceInfoVec(service_name_, method_name_, GetServices()); - SServiceMethodInformation service_method_info = GetHighestQualityServiceMethodInformation(service_method_info_vec); - req_desc_ = service_method_info.request_type.descriptor; + const SServiceMethodInformation service_method_info = GetHighestQualityServiceMethodInformation(service_method_info_vec); + req_desc_ = service_method_info.request_type.descriptor; resp_desc_ = service_method_info.response_type.descriptor; return !service_method_info_vec.empty(); @@ -547,7 +549,7 @@ namespace eCAL { std::vector service_method_info_vec = GetQualityServiceInfoVec(client_name_, method_name_, GetClients()); - SServiceMethodInformation service_method_info = GetHighestQualityServiceMethodInformation(service_method_info_vec); + const SServiceMethodInformation service_method_info = GetHighestQualityServiceMethodInformation(service_method_info_vec); req_type_ = service_method_info.request_type.name; resp_type_ = service_method_info.response_type.name; @@ -558,7 +560,7 @@ namespace eCAL { std::vector service_method_info_vec = GetQualityServiceInfoVec(client_name_, method_name_, GetClients()); - SServiceMethodInformation service_method_info = GetHighestQualityServiceMethodInformation(service_method_info_vec); + const SServiceMethodInformation service_method_info = GetHighestQualityServiceMethodInformation(service_method_info_vec); req_desc_ = service_method_info.request_type.descriptor; resp_desc_ = service_method_info.response_type.descriptor; diff --git a/ecal/tests/cpp/util_test/src/util_getclients.cpp b/ecal/tests/cpp/util_test/src/util_getclients.cpp index 922e465e66..f644966797 100644 --- a/ecal/tests/cpp/util_test/src/util_getclients.cpp +++ b/ecal/tests/cpp/util_test/src/util_getclients.cpp @@ -22,24 +22,23 @@ #include -#define CMN_REGISTRATION_REFRESH 1000 -#define CMN_MONITORING_TIMEOUT 5000 +#define CMN_MONITORING_TIMEOUT 5000 -TEST(core_cpp_util, GetClients) +TEST(core_cpp_util, ClientExpiration) { // initialize eCAL API - eCAL::Initialize(0, nullptr, "util_getclients"); + eCAL::Initialize(0, nullptr, "core_cpp_util"); std::map, eCAL::SServiceMethodInformation> client_info_map; - - // add and expire simple client + + // create simple client and let it expire { // create client eCAL::SServiceMethodInformation service_method_info; - service_method_info.request_type.name = "foo::req_type1"; - service_method_info.request_type.descriptor = "foo::req_desc1"; - service_method_info.response_type.name = "foo::resp_type1"; - service_method_info.response_type.descriptor = "foo::resp_desc1"; + service_method_info.request_type.name = "foo::req_type"; + service_method_info.request_type.descriptor = "foo::req_desc"; + service_method_info.response_type.name = "foo::resp_type"; + service_method_info.response_type.descriptor = "foo::resp_desc"; eCAL::CServiceClient client("foo::service", { {"foo::method", service_method_info} }); // get all clients @@ -48,6 +47,16 @@ TEST(core_cpp_util, GetClients) // check size EXPECT_EQ(client_info_map.size(), 1); + // check client/method names + std::vector> client_method_names; + eCAL::Util::GetClientMethodNames(client_method_names); + EXPECT_EQ(client_method_names.size(), 1); + for (const auto& method_name : client_method_names) + { + EXPECT_EQ(std::get<0>(method_name), "foo::service"); + EXPECT_EQ(std::get<1>(method_name), "foo::method"); + } + // let's wait a monitoring timeout long eCAL::Process::SleepMS(CMN_MONITORING_TIMEOUT); @@ -65,7 +74,18 @@ TEST(core_cpp_util, GetClients) // check size EXPECT_EQ(client_info_map.size(), 0); - // create 2 clients + // finalize eCAL API + eCAL::Finalize(); +} + +TEST(core_cpp_util, ClientEqualQualities) +{ + // initialize eCAL API + eCAL::Initialize(0, nullptr, "core_cpp_util"); + + std::map, eCAL::SServiceMethodInformation> client_info_map; + + // create 2 clients with the same quality of data type information { // create client 1 eCAL::SServiceMethodInformation service_method_info1; @@ -92,18 +112,8 @@ TEST(core_cpp_util, GetClients) EXPECT_EQ(req_desc, "foo::req_desc1"); EXPECT_EQ(resp_desc, "foo::resp_desc1"); - // check client/method names - std::vector> client_method_names; - eCAL::Util::GetClientMethodNames(client_method_names); - EXPECT_EQ(client_method_names.size(), 1); - for (const auto& method_name : client_method_names) - { - EXPECT_EQ(std::get<0>(method_name), "foo::service"); - EXPECT_EQ(std::get<1>(method_name), "foo::method"); - } - // create client 2 - // this will not overwrite the attributes from client1 + // this will not overwrite the attributes from client 1, because the quality is not higher eCAL::SServiceMethodInformation service_method_info2; service_method_info2.request_type.name = "foo::req_type2"; service_method_info2.request_type.descriptor = "foo::req_desc2"; @@ -119,13 +129,13 @@ TEST(core_cpp_util, GetClients) EXPECT_EQ(req_desc, "foo::req_desc1"); EXPECT_EQ(resp_desc, "foo::resp_desc1"); - // check size (client1 replaced by client2) + // check size it's client 1 only EXPECT_EQ(client_info_map.size(), 1); // let's wait a monitoring timeout long eCAL::Process::SleepMS(CMN_MONITORING_TIMEOUT); - // get all clients again, client should not be expired + // get all clients again, clients should not be expired eCAL::Util::GetClients(client_info_map); // check size @@ -134,10 +144,78 @@ TEST(core_cpp_util, GetClients) // destroy client 1 client1.Destroy(); - // check attributes (client 1 should be replaced by client 2 immediately) + // check attributes, client 1 attributes should be replaced by client 2 attributes now eCAL::Util::GetClientTypeNames("foo::service", "foo::method", req_type, resp_type); - EXPECT_EQ(req_type, "foo::req_type2"); + EXPECT_EQ(req_type, "foo::req_type2"); EXPECT_EQ(resp_type, "foo::resp_type2"); + eCAL::Util::GetClientDescription("foo::service", "foo::method", req_desc, resp_desc); + EXPECT_EQ(req_desc, "foo::req_desc2"); + EXPECT_EQ(resp_desc, "foo::resp_desc2"); + } + + // get all clients again, all clients + // should be removed from the map + eCAL::Util::GetClients(client_info_map); + + // check size + EXPECT_EQ(client_info_map.size(), 0); + + // finalize eCAL API + eCAL::Finalize(); +} + +TEST(core_cpp_util, ClientDifferentQualities) +{ + // initialize eCAL API + eCAL::Initialize(0, nullptr, "core_cpp_util"); + + std::map, eCAL::SServiceMethodInformation> client_info_map; + + // create 2 clients with different qualities of data type information + { + // create client 1, response type name and reponse description are missing + eCAL::SServiceMethodInformation service_method_info1; + service_method_info1.request_type.name = "foo::req_type1"; + service_method_info1.request_type.descriptor = "foo::req_desc1"; + service_method_info1.response_type.name = ""; + service_method_info1.response_type.descriptor = ""; + eCAL::CServiceClient client1("foo::service", { {"foo::method", service_method_info1} }); + + // get all clients + eCAL::Util::GetClients(client_info_map); + + // check size + EXPECT_EQ(client_info_map.size(), 1); + + // check attributes + std::string req_type, resp_type; + std::string req_desc, resp_desc; + + eCAL::Util::GetClientTypeNames("foo::service", "foo::method", req_type, resp_type); + EXPECT_EQ(req_type, "foo::req_type1"); + EXPECT_EQ(resp_type, ""); + eCAL::Util::GetClientDescription("foo::service", "foo::method", req_desc, resp_desc); + EXPECT_EQ(req_desc, "foo::req_desc1"); + EXPECT_EQ(resp_desc, ""); + + // create client 2, with higher quality than client 1 + eCAL::SServiceMethodInformation service_method_info2; + service_method_info2.request_type.name = "foo::req_type2"; + service_method_info2.request_type.descriptor = "foo::req_desc2"; + service_method_info2.response_type.name = "foo::resp_type2"; + service_method_info2.response_type.descriptor = "foo::resp_desc2"; + eCAL::CServiceClient client2("foo::service", { {"foo::method", service_method_info2} }); + + // check attributes, we expect attributes from client 2 here + eCAL::Util::GetClientTypeNames("foo::service", "foo::method", req_type, resp_type); + EXPECT_EQ(req_type, "foo::req_type2"); + EXPECT_EQ(resp_type, "foo::resp_type2"); + eCAL::Util::GetClientDescription("foo::service", "foo::method", req_desc, resp_desc); + EXPECT_EQ(req_desc, "foo::req_desc2"); + EXPECT_EQ(resp_desc, "foo::resp_desc2"); + + // check size it's client 2 only + EXPECT_EQ(client_info_map.size(), 1); } // get all clients again, all clients diff --git a/ecal/tests/cpp/util_test/src/util_getservices.cpp b/ecal/tests/cpp/util_test/src/util_getservices.cpp index 0a6837785d..cebf0f3061 100644 --- a/ecal/tests/cpp/util_test/src/util_getservices.cpp +++ b/ecal/tests/cpp/util_test/src/util_getservices.cpp @@ -24,27 +24,35 @@ #define CMN_MONITORING_TIMEOUT 5000 -TEST(core_cpp_util, GetServices) +TEST(core_cpp_util, ServiceExpiration) { // initialize eCAL API - eCAL::Initialize(0, nullptr, "util_getservices"); + eCAL::Initialize(0, nullptr, "core_cpp_util"); std::map, eCAL::SServiceMethodInformation> service_info_map; - - // add and expire simple service - { - // create server - eCAL::CServiceServer server("foo::service"); - // add a description only - server.AddDescription("foo::method1", "foo::req_type1", "foo::req_desc1", "foo::resp_type1", "foo::resp_desc1"); + // create simple service and let it expire + { + // create service + eCAL::CServiceServer service("foo::service"); + service.AddDescription("foo::method", "foo::req_type", "foo::req_desc", "foo::resp_type", "foo::resp_desc"); - // get all service + // get all services eCAL::Util::GetServices(service_info_map); // check size EXPECT_EQ(service_info_map.size(), 1); + // check service/method names + std::vector> service_method_names; + eCAL::Util::GetServiceMethodNames(service_method_names); + EXPECT_EQ(service_method_names.size(), 1); + for (const auto& method_name : service_method_names) + { + EXPECT_EQ(std::get<0>(method_name), "foo::service"); + EXPECT_EQ(std::get<1>(method_name), "foo::method"); + } + // let's wait a monitoring timeout long eCAL::Process::SleepMS(CMN_MONITORING_TIMEOUT); @@ -55,27 +63,31 @@ TEST(core_cpp_util, GetServices) EXPECT_EQ(service_info_map.size(), 1); } - // get all services again, all services + // get all services again, all services // should be removed from the map eCAL::Util::GetServices(service_info_map); // check size EXPECT_EQ(service_info_map.size(), 0); - // add a service with method callback - { - // create server - eCAL::CServiceServer server("foo::service"); + // finalize eCAL API + eCAL::Finalize(); +} - auto method_callback = [&](const std::string& /*method_*/, const std::string& /*req_type_*/, const std::string& /*resp_type_*/, const std::string& /*request_*/, std::string& /*response_*/) -> int - { - return 42; - }; +TEST(core_cpp_util, ServiceEqualQualities) +{ + // initialize eCAL API + eCAL::Initialize(0, nullptr, "core_cpp_util"); - // add method callback - server.AddMethodCallback("foo::method1", "foo::req_type1", "foo::resp_type1", method_callback); + std::map, eCAL::SServiceMethodInformation> service_info_map; + + // create 2 services with the same quality of data type information + { + // create service 1 + eCAL::CServiceServer service1("foo::service"); + service1.AddDescription("foo::method", "foo::req_type1", "foo::req_desc1", "foo::resp_type1", "foo::resp_desc1"); - // get all service + // get all services eCAL::Util::GetServices(service_info_map); // check size @@ -85,43 +97,48 @@ TEST(core_cpp_util, GetServices) std::string req_type, resp_type; std::string req_desc, resp_desc; - eCAL::Util::GetServiceTypeNames("foo::service", "foo::method1", req_type, resp_type); + eCAL::Util::GetServiceTypeNames("foo::service", "foo::method", req_type, resp_type); EXPECT_EQ(req_type, "foo::req_type1"); EXPECT_EQ(resp_type, "foo::resp_type1"); - eCAL::Util::GetServiceDescription("foo::service", "foo::method1", req_desc, resp_desc); - EXPECT_EQ(req_desc, ""); - EXPECT_EQ(resp_desc, ""); + eCAL::Util::GetServiceDescription("foo::service", "foo::method", req_desc, resp_desc); + EXPECT_EQ(req_desc, "foo::req_desc1"); + EXPECT_EQ(resp_desc, "foo::resp_desc1"); - // change attributes - server.AddDescription("foo::method1", "foo::req_type1-1", "foo::req_desc1-1", "foo::resp_type1-1", "foo::resp_desc1-1"); + // create service 2 + // this will not overwrite the attributes from service 1, because the quality is not higher + eCAL::CServiceServer service2("foo::service"); + service2.AddDescription("foo::method", "foo::req_type2", "foo::req_desc2", "foo::resp_type2", "foo::resp_desc2"); // check attributes - eCAL::Util::GetServiceTypeNames("foo::service", "foo::method1", req_type, resp_type); - EXPECT_EQ(req_type, "foo::req_type1-1"); - EXPECT_EQ(resp_type, "foo::resp_type1-1"); - eCAL::Util::GetServiceDescription("foo::service", "foo::method1", req_desc, resp_desc); - EXPECT_EQ(req_desc, "foo::req_desc1-1"); - EXPECT_EQ(resp_desc, "foo::resp_desc1-1"); - - // change attributes again (this will not overwrite the attributes anymore) - server.AddDescription("foo::method1", "foo::req_type1-2", "foo::req_desc1-2", "foo::resp_type1-2", "foo::resp_desc1-2"); + eCAL::Util::GetServiceTypeNames("foo::service", "foo::method", req_type, resp_type); + EXPECT_EQ(req_type, "foo::req_type1"); + EXPECT_EQ(resp_type, "foo::resp_type1"); + eCAL::Util::GetServiceDescription("foo::service", "foo::method", req_desc, resp_desc); + EXPECT_EQ(req_desc, "foo::req_desc1"); + EXPECT_EQ(resp_desc, "foo::resp_desc1"); - // check attributes - eCAL::Util::GetServiceTypeNames("foo::service", "foo::method1", req_type, resp_type); - EXPECT_EQ(req_type, "foo::req_type1-1"); - EXPECT_EQ(resp_type, "foo::resp_type1-1"); - eCAL::Util::GetServiceDescription("foo::service", "foo::method1", req_desc, resp_desc); - EXPECT_EQ(req_desc, "foo::req_desc1-1"); - EXPECT_EQ(resp_desc, "foo::resp_desc1-1"); + // check size it's service 1 only + EXPECT_EQ(service_info_map.size(), 1); // let's wait a monitoring timeout long eCAL::Process::SleepMS(CMN_MONITORING_TIMEOUT); - // get all services again, service should not be expired + // get all services again, services should not be expired eCAL::Util::GetServices(service_info_map); // check size EXPECT_EQ(service_info_map.size(), 1); + + // destroy service 1 + service1.Destroy(); + + // check attributes, service 1 attributes should be replaced by service 2 attributes now + eCAL::Util::GetServiceTypeNames("foo::service", "foo::method", req_type, resp_type); + EXPECT_EQ(req_type, "foo::req_type2"); + EXPECT_EQ(resp_type, "foo::resp_type2"); + eCAL::Util::GetServiceDescription("foo::service", "foo::method", req_desc, resp_desc); + EXPECT_EQ(req_desc, "foo::req_desc2"); + EXPECT_EQ(resp_desc, "foo::resp_desc2"); } // get all services again, all services @@ -134,3 +151,60 @@ TEST(core_cpp_util, GetServices) // finalize eCAL API eCAL::Finalize(); } + +TEST(core_cpp_util, ServiceDifferentQualities) +{ + // initialize eCAL API + eCAL::Initialize(0, nullptr, "core_cpp_util"); + + std::map, eCAL::SServiceMethodInformation> service_info_map; + + // create 2 services with different qualities of data type information + { + // create service 1, response type name and response description are missing + eCAL::CServiceServer service1("foo::service"); + service1.AddDescription("foo::method", "foo::req_type1", "foo::req_desc1", "", ""); + + // get all services + eCAL::Util::GetServices(service_info_map); + + // check size + EXPECT_EQ(service_info_map.size(), 1); + + // check attributes + std::string req_type, resp_type; + std::string req_desc, resp_desc; + + eCAL::Util::GetServiceTypeNames("foo::service", "foo::method", req_type, resp_type); + EXPECT_EQ(req_type, "foo::req_type1"); + EXPECT_EQ(resp_type, ""); + eCAL::Util::GetServiceDescription("foo::service", "foo::method", req_desc, resp_desc); + EXPECT_EQ(req_desc, "foo::req_desc1"); + EXPECT_EQ(resp_desc, ""); + + // create service 2, with higher quality than service 1 + eCAL::CServiceServer service2("foo::service"); + service2.AddDescription("foo::method", "foo::req_type2", "foo::req_desc2", "foo::resp_type2", "foo::resp_desc2"); + + // check attributes, we expect attributes from service 2 here + eCAL::Util::GetServiceTypeNames("foo::service", "foo::method", req_type, resp_type); + EXPECT_EQ(req_type, "foo::req_type2"); + EXPECT_EQ(resp_type, "foo::resp_type2"); + eCAL::Util::GetServiceDescription("foo::service", "foo::method", req_desc, resp_desc); + EXPECT_EQ(req_desc, "foo::req_desc2"); + EXPECT_EQ(resp_desc, "foo::resp_desc2"); + + // check size it's service 2 only + EXPECT_EQ(service_info_map.size(), 1); + } + + // get all services again, all services + // should be removed from the map + eCAL::Util::GetServices(service_info_map); + + // check size + EXPECT_EQ(service_info_map.size(), 0); + + // finalize eCAL API + eCAL::Finalize(); +} diff --git a/ecal/tests/cpp/util_test/src/util_gettopics.cpp b/ecal/tests/cpp/util_test/src/util_gettopics.cpp index c8d739e03d..70a48c8c63 100644 --- a/ecal/tests/cpp/util_test/src/util_gettopics.cpp +++ b/ecal/tests/cpp/util_test/src/util_gettopics.cpp @@ -25,13 +25,12 @@ #include -#define CMN_REGISTRATION_REFRESH 1000 -#define CMN_MONITORING_TIMEOUT 5000 +#define CMN_MONITORING_TIMEOUT 5000 TEST(core_cpp_util, GetTopics) { // initialize eCAL API - eCAL::Initialize(0, nullptr, "pubsub_gettopics"); + eCAL::Initialize(0, nullptr, "core_cpp_util"); std::map topic_info_map; @@ -129,7 +128,8 @@ TEST(core_cpp_util, GetTopicsParallel) constexpr const int waiting_time_thread(1000); constexpr const int parallel_threads(1); - eCAL::Initialize(); + // initialize eCAL API + eCAL::Initialize(0, nullptr, "core_cpp_util"); auto create_publishers = [&]() { std::string topic_name = "Test.ParallelUtilFunctions"; @@ -186,5 +186,6 @@ TEST(core_cpp_util, GetTopicsParallel) EXPECT_EQ(final_topic_names.size(), 0); EXPECT_EQ(final_topics.size(), 0); + // finalize eCAL API eCAL::Finalize(); } From 96d7fa806dba3c660b4eaf10bb8796c39f825f76 Mon Sep 17 00:00:00 2001 From: rex-schilasky <49162693+rex-schilasky@users.noreply.github.com> Date: Mon, 15 Apr 2024 14:54:50 +0200 Subject: [PATCH 11/27] clang-tidy --- ecal/core/src/ecal_descgate.h | 6 +++--- ecal/tests/cpp/util_test/src/util_getclients.cpp | 2 +- ecal/tests/cpp/util_test/src/util_getservices.cpp | 2 +- ecal/tests/cpp/util_test/src/util_gettopics.cpp | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/ecal/core/src/ecal_descgate.h b/ecal/core/src/ecal_descgate.h index 6ae6de2316..45c4d022f1 100644 --- a/ecal/core/src/ecal_descgate.h +++ b/ecal/core/src/ecal_descgate.h @@ -128,7 +128,7 @@ namespace eCAL const std::string& topic_name_, const std::string& topic_id_, const SDataTypeInformation& topic_info_, - const Util::DescQualityFlags topic_quality_); + Util::DescQualityFlags topic_quality_); void RemTopicDescription(SQualityTopicIdMap& topic_info_map_, const std::string& topic_name_, @@ -140,8 +140,8 @@ namespace eCAL const std::string& method_name_, const SDataTypeInformation& request_type_information_, const SDataTypeInformation& response_type_information_, - const Util::DescQualityFlags request_type_quality_, - const Util::DescQualityFlags response_type_quality_); + Util::DescQualityFlags request_type_quality_, + Util::DescQualityFlags response_type_quality_); void RemServiceDescription(SQualityServiceIdMap& service_method_info_map_, const std::string& service_name_, diff --git a/ecal/tests/cpp/util_test/src/util_getclients.cpp b/ecal/tests/cpp/util_test/src/util_getclients.cpp index f644966797..b21b5af25f 100644 --- a/ecal/tests/cpp/util_test/src/util_getclients.cpp +++ b/ecal/tests/cpp/util_test/src/util_getclients.cpp @@ -22,7 +22,7 @@ #include -#define CMN_MONITORING_TIMEOUT 5000 +enum { CMN_MONITORING_TIMEOUT = 5000}; TEST(core_cpp_util, ClientExpiration) { diff --git a/ecal/tests/cpp/util_test/src/util_getservices.cpp b/ecal/tests/cpp/util_test/src/util_getservices.cpp index cebf0f3061..b5faaf4659 100644 --- a/ecal/tests/cpp/util_test/src/util_getservices.cpp +++ b/ecal/tests/cpp/util_test/src/util_getservices.cpp @@ -22,7 +22,7 @@ #include -#define CMN_MONITORING_TIMEOUT 5000 +enum { CMN_MONITORING_TIMEOUT = 5000 }; TEST(core_cpp_util, ServiceExpiration) { diff --git a/ecal/tests/cpp/util_test/src/util_gettopics.cpp b/ecal/tests/cpp/util_test/src/util_gettopics.cpp index 70a48c8c63..363cc72688 100644 --- a/ecal/tests/cpp/util_test/src/util_gettopics.cpp +++ b/ecal/tests/cpp/util_test/src/util_gettopics.cpp @@ -25,7 +25,7 @@ #include -#define CMN_MONITORING_TIMEOUT 5000 +enum { CMN_MONITORING_TIMEOUT = 5000 }; TEST(core_cpp_util, GetTopics) { From 46d630a03b01c26b0464c32e0522aa9a0d22f66b Mon Sep 17 00:00:00 2001 From: rex-schilasky <49162693+rex-schilasky@users.noreply.github.com> Date: Mon, 15 Apr 2024 16:57:23 +0200 Subject: [PATCH 12/27] cut descgate interfaces to config, registration receiver and registration provider (to make it testable) --- ecal/core/src/ecal_descgate.cpp | 36 +++++-------------- ecal/core/src/ecal_descgate.h | 16 ++++----- ecal/core/src/ecal_globals.cpp | 21 +++++++++-- .../cpp/util_test/src/util_getclients.cpp | 14 +++++++- .../cpp/util_test/src/util_getservices.cpp | 14 +++++++- .../cpp/util_test/src/util_gettopics.cpp | 9 +++-- 6 files changed, 66 insertions(+), 44 deletions(-) diff --git a/ecal/core/src/ecal_descgate.cpp b/ecal/core/src/ecal_descgate.cpp index b4ded553ac..5f6004ea83 100644 --- a/ecal/core/src/ecal_descgate.cpp +++ b/ecal/core/src/ecal_descgate.cpp @@ -21,12 +21,10 @@ * @brief eCAL description gateway class **/ -#include -#include - -#include "ecal_globals.h" #include "ecal_descgate.h" +#include + namespace { eCAL::Util::DescQualityFlags GetDataTypeInfoQuality(const eCAL::SDataTypeInformation& data_type_info_, bool is_producer_) @@ -45,33 +43,15 @@ namespace namespace eCAL { - CDescGate::CDescGate() : - m_publisher_info_map (std::chrono::milliseconds(Config::GetMonitoringTimeoutMs())), - m_subscriber_info_map (std::chrono::milliseconds(Config::GetMonitoringTimeoutMs())), - m_service_info_map (std::chrono::milliseconds(Config::GetMonitoringTimeoutMs())), - m_client_info_map (std::chrono::milliseconds(Config::GetMonitoringTimeoutMs())) + CDescGate::CDescGate(const std::chrono::milliseconds& exp_timeout_) : + m_publisher_info_map (exp_timeout_), + m_subscriber_info_map (exp_timeout_), + m_service_info_map (exp_timeout_), + m_client_info_map (exp_timeout_) { } CDescGate::~CDescGate() = default; - void CDescGate::Create() - { -#if ECAL_CORE_REGISTRATION - // utilize registration provider and receiver to get descriptions - g_registration_provider()->SetCustomApplySampleCallback("descgate", [this](const auto& sample_) {this->ApplySample(sample_, tl_none); }); - g_registration_receiver()->SetCustomApplySampleCallback("descgate", [this](const auto& sample_) {this->ApplySample(sample_, tl_none); }); -#endif - } - - void CDescGate::Destroy() - { -#if ECAL_CORE_REGISTRATION - // stop registration provider and receiver utilization to get descriptions - g_registration_provider()->RemCustomApplySampleCallback("descgate"); - g_registration_receiver()->RemCustomApplySampleCallback("descgate"); -#endif - } - QualityTopicIdMap CDescGate::GetPublisher() { return GetTopics(m_publisher_info_map); @@ -179,7 +159,7 @@ namespace eCAL break; default: { - Logging::Log(log_level_debug1, "CDescGate::ApplySample : unknown sample type"); + std::cerr << "CDescGate::ApplySample : unknown sample type" << '\n'; } break; } diff --git a/ecal/core/src/ecal_descgate.h b/ecal/core/src/ecal_descgate.h index 45c4d022f1..9e663762aa 100644 --- a/ecal/core/src/ecal_descgate.h +++ b/ecal/core/src/ecal_descgate.h @@ -26,13 +26,13 @@ #include #include -#include "serialization/ecal_serialize_sample_registration.h" +#include "serialization/ecal_struct_sample_registration.h" #include "util/ecal_expmap.h" +#include #include #include #include -#include namespace eCAL { @@ -65,21 +65,23 @@ namespace eCAL } }; - using QualityTopicIdMap = std::map; + using QualityTopicIdMap = std::map; using QualityServiceIdMap = std::map; class CDescGate { public: - CDescGate(); + CDescGate(const std::chrono::milliseconds& exp_timeout_); ~CDescGate(); - void Create(); - void Destroy(); + // apply samples to description gate + void ApplySample(const Registration::Sample& sample_, eTLayerType layer_); + // get publisher/subscriber maps QualityTopicIdMap GetPublisher(); QualityTopicIdMap GetSubscriber(); + // get service/clients maps QualityServiceIdMap GetServices(); QualityServiceIdMap GetClients(); @@ -122,8 +124,6 @@ namespace eCAL QualityTopicIdMap GetTopics(const SQualityTopicIdMap& topic_map_); QualityServiceIdMap GetServices(const SQualityServiceIdMap& service_method_info_map_); - void ApplySample(const Registration::Sample& sample_, eTLayerType layer_); - void ApplyTopicDescription(SQualityTopicIdMap& topic_info_map_, const std::string& topic_name_, const std::string& topic_id_, diff --git a/ecal/core/src/ecal_globals.cpp b/ecal/core/src/ecal_globals.cpp index 634fdfc3b2..5270b2e2d3 100644 --- a/ecal/core/src/ecal_globals.cpp +++ b/ecal/core/src/ecal_globals.cpp @@ -105,7 +105,8 @@ namespace eCAL ///////////////////// if (descgate_instance == nullptr) { - descgate_instance = std::make_unique(); + // create description gate with configured expiration timeout + descgate_instance = std::make_unique(std::chrono::milliseconds(Config::GetMonitoringTimeoutMs())); new_initialization = true; } @@ -232,7 +233,14 @@ namespace eCAL if (registration_provider_instance) registration_provider_instance->Create(); if (registration_receiver_instance) registration_receiver_instance->Create(); #endif - if (descgate_instance) descgate_instance->Create(); + if (descgate_instance) + { +#if ECAL_CORE_REGISTRATION + // utilize registration provider and receiver to get descriptions + g_registration_provider()->SetCustomApplySampleCallback("descgate", [](const auto& sample_) {g_descgate()->ApplySample(sample_, tl_none); }); + g_registration_receiver()->SetCustomApplySampleCallback("descgate", [](const auto& sample_) {g_descgate()->ApplySample(sample_, tl_none); }); +#endif + } #if defined(ECAL_CORE_REGISTRATION_SHM) || defined(ECAL_CORE_TRANSPORT_SHM) if (memfile_pool_instance) memfile_pool_instance->Create(); #endif @@ -324,7 +332,14 @@ namespace eCAL #if ECAL_CORE_SUBSCRIBER if (subgate_instance) subgate_instance->Destroy(); #endif - if (descgate_instance) descgate_instance->Destroy(); + if (descgate_instance) + { +#if ECAL_CORE_REGISTRATION + // stop registration provider and receiver utilization to get descriptions + g_registration_provider()->RemCustomApplySampleCallback("descgate"); + g_registration_receiver()->RemCustomApplySampleCallback("descgate"); +#endif + } #if ECAL_CORE_REGISTRATION if (registration_receiver_instance) registration_receiver_instance->Destroy(); if (registration_provider_instance) registration_provider_instance->Destroy(); diff --git a/ecal/tests/cpp/util_test/src/util_getclients.cpp b/ecal/tests/cpp/util_test/src/util_getclients.cpp index b21b5af25f..3a7543d7e6 100644 --- a/ecal/tests/cpp/util_test/src/util_getclients.cpp +++ b/ecal/tests/cpp/util_test/src/util_getclients.cpp @@ -22,7 +22,10 @@ #include -enum { CMN_MONITORING_TIMEOUT = 5000}; +enum { + CMN_MONITORING_TIMEOUT = 5000, + CMN_REGISTRATION_REFRESH = 1000 +}; TEST(core_cpp_util, ClientExpiration) { @@ -67,6 +70,9 @@ TEST(core_cpp_util, ClientExpiration) EXPECT_EQ(client_info_map.size(), 1); } + // let's unregister + eCAL::Process::SleepMS(CMN_REGISTRATION_REFRESH); + // get all clients again, all clients // should be removed from the map eCAL::Util::GetClients(client_info_map); @@ -153,6 +159,9 @@ TEST(core_cpp_util, ClientEqualQualities) EXPECT_EQ(resp_desc, "foo::resp_desc2"); } + // let's unregister + eCAL::Process::SleepMS(CMN_REGISTRATION_REFRESH); + // get all clients again, all clients // should be removed from the map eCAL::Util::GetClients(client_info_map); @@ -218,6 +227,9 @@ TEST(core_cpp_util, ClientDifferentQualities) EXPECT_EQ(client_info_map.size(), 1); } + // let's unregister + eCAL::Process::SleepMS(CMN_REGISTRATION_REFRESH); + // get all clients again, all clients // should be removed from the map eCAL::Util::GetClients(client_info_map); diff --git a/ecal/tests/cpp/util_test/src/util_getservices.cpp b/ecal/tests/cpp/util_test/src/util_getservices.cpp index b5faaf4659..03a325589c 100644 --- a/ecal/tests/cpp/util_test/src/util_getservices.cpp +++ b/ecal/tests/cpp/util_test/src/util_getservices.cpp @@ -22,7 +22,10 @@ #include -enum { CMN_MONITORING_TIMEOUT = 5000 }; +enum { + CMN_MONITORING_TIMEOUT = 5000, + CMN_REGISTRATION_REFRESH = 1000 +}; TEST(core_cpp_util, ServiceExpiration) { @@ -63,6 +66,9 @@ TEST(core_cpp_util, ServiceExpiration) EXPECT_EQ(service_info_map.size(), 1); } + // let's unregister + eCAL::Process::SleepMS(CMN_REGISTRATION_REFRESH); + // get all services again, all services // should be removed from the map eCAL::Util::GetServices(service_info_map); @@ -141,6 +147,9 @@ TEST(core_cpp_util, ServiceEqualQualities) EXPECT_EQ(resp_desc, "foo::resp_desc2"); } + // let's unregister + eCAL::Process::SleepMS(CMN_REGISTRATION_REFRESH); + // get all services again, all services // should be removed from the map eCAL::Util::GetServices(service_info_map); @@ -198,6 +207,9 @@ TEST(core_cpp_util, ServiceDifferentQualities) EXPECT_EQ(service_info_map.size(), 1); } + // let's unregister + eCAL::Process::SleepMS(CMN_REGISTRATION_REFRESH); + // get all services again, all services // should be removed from the map eCAL::Util::GetServices(service_info_map); diff --git a/ecal/tests/cpp/util_test/src/util_gettopics.cpp b/ecal/tests/cpp/util_test/src/util_gettopics.cpp index 363cc72688..7e6af479ad 100644 --- a/ecal/tests/cpp/util_test/src/util_gettopics.cpp +++ b/ecal/tests/cpp/util_test/src/util_gettopics.cpp @@ -25,7 +25,10 @@ #include -enum { CMN_MONITORING_TIMEOUT = 5000 }; +enum { + CMN_MONITORING_TIMEOUT = 5000, + CMN_REGISTRATION_REFRESH = 1000 +}; TEST(core_cpp_util, GetTopics) { @@ -108,8 +111,8 @@ TEST(core_cpp_util, GetTopics) } } - // let's unregister them - eCAL::Process::SleepMS(CMN_MONITORING_TIMEOUT + 2000); + // let's unregister + eCAL::Process::SleepMS(CMN_REGISTRATION_REFRESH); // get all topics again, now all topics // should be removed from the map From 7c622643ddd7cfeb9882ea62b69e2938f69f5f55 Mon Sep 17 00:00:00 2001 From: rex-schilasky <49162693+rex-schilasky@users.noreply.github.com> Date: Mon, 15 Apr 2024 18:28:31 +0200 Subject: [PATCH 13/27] simple descgate test added --- ecal/tests/CMakeLists.txt | 11 ++-- ecal/tests/cpp/descgate_test/CMakeLists.txt | 46 ++++++++++++++++ .../cpp/descgate_test/src/getpublisher.cpp | 52 +++++++++++++++++++ 3 files changed, 105 insertions(+), 4 deletions(-) create mode 100644 ecal/tests/cpp/descgate_test/CMakeLists.txt create mode 100644 ecal/tests/cpp/descgate_test/src/getpublisher.cpp diff --git a/ecal/tests/CMakeLists.txt b/ecal/tests/CMakeLists.txt index 7791c4b6b3..bd6a0c250b 100644 --- a/ecal/tests/CMakeLists.txt +++ b/ecal/tests/CMakeLists.txt @@ -28,6 +28,13 @@ add_subdirectory(c/core_test) # -------------------------------------------------------- add_subdirectory(cpp/core_test) +add_subdirectory(cpp/descgate_test) + +if(ECAL_CORE_REGISTRATION AND ECAL_CORE_PUBLISHER) + add_subdirectory(cpp/util_test) +endif() + + @@ -36,10 +43,6 @@ add_subdirectory(cpp/expmap_test) add_subdirectory(cpp/serialization_test) add_subdirectory(cpp/topic2mcast_test) -if(ECAL_CORE_REGISTRATION AND ECAL_CORE_PUBLISHER) - add_subdirectory(cpp/util_test) -endif() - if(ECAL_CORE_REGISTRATION_SHM OR ECAL_CORE_TRANSPORT_SHM) add_subdirectory(cpp/io_memfile_test) endif() diff --git a/ecal/tests/cpp/descgate_test/CMakeLists.txt b/ecal/tests/cpp/descgate_test/CMakeLists.txt new file mode 100644 index 0000000000..030b026879 --- /dev/null +++ b/ecal/tests/cpp/descgate_test/CMakeLists.txt @@ -0,0 +1,46 @@ +# ========================= eCAL LICENSE ================================= +# +# Copyright (C) 2016 - 2019 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 ================================= + +project(test_descgate) + +find_package(Threads REQUIRED) +find_package(GTest REQUIRED) + +set(descgate_test_src + src/getpublisher.cpp + ../../../core/src/ecal_descgate.cpp +) + +ecal_add_gtest(${PROJECT_NAME} ${descgate_test_src}) + +target_include_directories(${PROJECT_NAME} PRIVATE $) + +target_link_libraries(${PROJECT_NAME} + PRIVATE + Threads::Threads +) + +target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_14) + +ecal_install_gtest(${PROJECT_NAME}) + +set_property(TARGET ${PROJECT_NAME} PROPERTY FOLDER tests/cpp/core) + +source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" FILES + ${${PROJECT_NAME}_src} +) diff --git a/ecal/tests/cpp/descgate_test/src/getpublisher.cpp b/ecal/tests/cpp/descgate_test/src/getpublisher.cpp new file mode 100644 index 0000000000..0b285c6504 --- /dev/null +++ b/ecal/tests/cpp/descgate_test/src/getpublisher.cpp @@ -0,0 +1,52 @@ +/* ========================= eCAL LICENSE ================================= + * + * Copyright (C) 2016 - 2019 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 ================================= +*/ + +#include "ecal_descgate.h" + +#include + +TEST(core_cpp_descgate, GetPublisher) +{ +#if 0 + constexpr int desc_gate_expiration_ms(5000); + eCAL::CDescGate desc_gate(std::chrono::milliseconds(desc_gate_expiration_ms)); + + auto pub_map = desc_gate.GetPublisher(); + EXPECT_EQ(0, pub_map.size()); +#else + constexpr int desc_gate_expiration_ms(5000); + auto desc_gate = std::make_shared(std::chrono::milliseconds(desc_gate_expiration_ms)); + + auto pub_map = desc_gate->GetPublisher(); + EXPECT_EQ(0, pub_map.size()); + + eCAL::Registration::Sample reg_sample; + reg_sample.cmd_type = eCAL::bct_reg_publisher; + + auto& ecal_reg_sample_topic = reg_sample.topic; + ecal_reg_sample_topic.tname = "foo"; + ecal_reg_sample_topic.tid = "12345"; + + desc_gate->ApplySample(reg_sample, eCAL::tl_none); + + pub_map = desc_gate->GetPublisher(); + EXPECT_EQ(0, pub_map.size()); + +#endif +} From 79cc99344ecedeef66e5655c4941b26422522370 Mon Sep 17 00:00:00 2001 From: rex-schilasky <49162693+rex-schilasky@users.noreply.github.com> Date: Tue, 16 Apr 2024 17:37:35 +0200 Subject: [PATCH 14/27] desc_gate added --- .../cpp/descgate_test/src/getpublisher.cpp | 283 ++++++++++++++++-- 1 file changed, 263 insertions(+), 20 deletions(-) diff --git a/ecal/tests/cpp/descgate_test/src/getpublisher.cpp b/ecal/tests/cpp/descgate_test/src/getpublisher.cpp index 0b285c6504..86dc0ec262 100644 --- a/ecal/tests/cpp/descgate_test/src/getpublisher.cpp +++ b/ecal/tests/cpp/descgate_test/src/getpublisher.cpp @@ -21,32 +21,275 @@ #include -TEST(core_cpp_descgate, GetPublisher) +#include +#include + +#define DESCGATE_EXPIRATION_MS 500 + +namespace +{ + eCAL::Registration::Sample CreatePublisher(const std::string& topic_name_) + { + eCAL::Registration::Sample reg_sample; + reg_sample.cmd_type = eCAL::bct_reg_publisher; + reg_sample.topic.tname = topic_name_; + reg_sample.topic.tid = topic_name_ + "-id"; + reg_sample.topic.tdatatype.name = topic_name_ + "-tdatatype.name"; + reg_sample.topic.tdatatype.encoding = topic_name_ + "-tdatatype.encoding"; + reg_sample.topic.tdatatype.descriptor = topic_name_ + "-tdatatype.descriptor"; + return reg_sample; + } + + eCAL::Registration::Sample CreateSubscriber(const std::string& topic_name_) + { + eCAL::Registration::Sample reg_sample; + reg_sample.cmd_type = eCAL::bct_reg_subscriber; + reg_sample.topic.tname = topic_name_; + reg_sample.topic.tid = topic_name_ + "-id"; + reg_sample.topic.tdatatype.name = topic_name_ + "-tdatatype.name"; + reg_sample.topic.tdatatype.encoding = topic_name_ + "-tdatatype.encoding"; + reg_sample.topic.tdatatype.descriptor = topic_name_ + "-tdatatype.descriptor"; + return reg_sample; + } + + eCAL::Registration::Sample CreateService(const std::string& service_name_) + { + eCAL::Registration::Sample reg_sample; + reg_sample.cmd_type = eCAL::bct_reg_service; + reg_sample.service.sname = service_name_; + reg_sample.service.sid = service_name_ + "-id"; + + eCAL::Service::Method method; + method.mname = "method_name"; + reg_sample.service.methods.push_back(method); + return reg_sample; + } + + eCAL::Registration::Sample CreateClient(const std::string& client_name_) + { + eCAL::Registration::Sample reg_sample; + reg_sample.cmd_type = eCAL::bct_reg_client; + reg_sample.client.sname = client_name_; + reg_sample.client.sid = client_name_ + "-id"; + + eCAL::Service::Method method; + method.mname = "method_name"; + reg_sample.client.methods.push_back(method); + return reg_sample; + } +} + +TEST(core_cpp_descgate, PublisherExpiration) +{ + eCAL::CDescGate desc_gate(std::chrono::milliseconds(DESCGATE_EXPIRATION_MS)); + + // apply sample 5 times, sample should not expire + auto runs(5); + while (runs--) + { + desc_gate.ApplySample(CreatePublisher("pub1"), eCAL::tl_none); + std::this_thread::sleep_for(std::chrono::milliseconds(DESCGATE_EXPIRATION_MS / 2)); + + EXPECT_EQ(1, desc_gate.GetPublisher().size()); + } + + // now let the sample expire + std::this_thread::sleep_for(std::chrono::milliseconds(DESCGATE_EXPIRATION_MS)); + + // sample should be expired + EXPECT_EQ(0, desc_gate.GetPublisher().size()); +} + +TEST(core_cpp_descgate, PublisherQualities) +{ + eCAL::CDescGate desc_gate(std::chrono::milliseconds(DESCGATE_EXPIRATION_MS)); + + // create and apply publisher pub1 + desc_gate.ApplySample(CreatePublisher("pub1"), eCAL::tl_none); + + // create and apply publisher pub2 + desc_gate.ApplySample(CreatePublisher("pub2"), eCAL::tl_none); + + // check gate size + auto sample_map = desc_gate.GetPublisher(); + EXPECT_EQ(2, sample_map.size()); + + // check pub1 quality + { + auto pub_it = sample_map.find({ "pub1", "pub1-id" }); + EXPECT_NE(pub_it, sample_map.end()); + if (pub_it != sample_map.end()) + { + EXPECT_EQ("pub1-id", pub_it->second.id); + EXPECT_EQ("pub1-tdatatype.name", pub_it->second.info.name); + EXPECT_EQ("pub1-tdatatype.encoding", pub_it->second.info.encoding); + EXPECT_EQ("pub1-tdatatype.descriptor", pub_it->second.info.descriptor); + } + } + + // check pub2 quality + { + auto pub_it = sample_map.find({ "pub2", "pub2-id" }); + EXPECT_NE(pub_it, sample_map.end()); + if (pub_it != sample_map.end()) + { + EXPECT_EQ("pub2-id", pub_it->second.id); + EXPECT_EQ("pub2-tdatatype.name", pub_it->second.info.name); + EXPECT_EQ("pub2-tdatatype.encoding", pub_it->second.info.encoding); + EXPECT_EQ("pub2-tdatatype.descriptor", pub_it->second.info.descriptor); + } + } + + // now let the sample expire + std::this_thread::sleep_for(std::chrono::milliseconds(DESCGATE_EXPIRATION_MS)); + + // sample should be expired + EXPECT_EQ(0, desc_gate.GetPublisher().size()); +} + +TEST(core_cpp_descgate, ManyPublisher) +{ + eCAL::CDescGate desc_gate(std::chrono::milliseconds(DESCGATE_EXPIRATION_MS)); + + constexpr int num_pub(1000); + for (auto pub = 0; pub < num_pub; ++pub) + { + // create registration sample for pub-xx + desc_gate.ApplySample(CreatePublisher("pub" + std::to_string(pub)), eCAL::tl_none); + } + + // map should contain num_pub samples + EXPECT_EQ(num_pub, desc_gate.GetPublisher().size()); + + // now let the samples expire + std::this_thread::sleep_for(std::chrono::milliseconds(DESCGATE_EXPIRATION_MS)); + + // samples should be expired + EXPECT_EQ(0, desc_gate.GetPublisher().size()); +} + +TEST(core_cpp_descgate, SubscriberExpiration) { -#if 0 - constexpr int desc_gate_expiration_ms(5000); - eCAL::CDescGate desc_gate(std::chrono::milliseconds(desc_gate_expiration_ms)); + eCAL::CDescGate desc_gate(std::chrono::milliseconds(DESCGATE_EXPIRATION_MS)); + + // apply sample 5 times, sample should not expire + auto runs(5); + while (runs--) + { + desc_gate.ApplySample(CreateSubscriber("sub1"), eCAL::tl_none); + std::this_thread::sleep_for(std::chrono::milliseconds(DESCGATE_EXPIRATION_MS / 2)); + + EXPECT_EQ(1, desc_gate.GetSubscriber().size()); + } + + // now let the sample expire + std::this_thread::sleep_for(std::chrono::milliseconds(DESCGATE_EXPIRATION_MS)); + + // sample should be expired + EXPECT_EQ(0, desc_gate.GetSubscriber().size()); +} + +TEST(core_cpp_descgate, ManySubscriber) +{ + eCAL::CDescGate desc_gate(std::chrono::milliseconds(DESCGATE_EXPIRATION_MS)); + + constexpr int num_sub(1000); + for (auto sub = 0; sub < num_sub; ++sub) + { + // create registration sample for sub-xx + desc_gate.ApplySample(CreateSubscriber("sub" + std::to_string(sub)), eCAL::tl_none); + } - auto pub_map = desc_gate.GetPublisher(); - EXPECT_EQ(0, pub_map.size()); -#else - constexpr int desc_gate_expiration_ms(5000); - auto desc_gate = std::make_shared(std::chrono::milliseconds(desc_gate_expiration_ms)); + // map should contain num_sub samples + EXPECT_EQ(num_sub, desc_gate.GetSubscriber().size()); - auto pub_map = desc_gate->GetPublisher(); - EXPECT_EQ(0, pub_map.size()); + // now let the samples expire + std::this_thread::sleep_for(std::chrono::milliseconds(DESCGATE_EXPIRATION_MS)); - eCAL::Registration::Sample reg_sample; - reg_sample.cmd_type = eCAL::bct_reg_publisher; + // samples should be expired + EXPECT_EQ(0, desc_gate.GetSubscriber().size()); +} + +TEST(core_cpp_descgate, ServiceExpiration) +{ + eCAL::CDescGate desc_gate(std::chrono::milliseconds(DESCGATE_EXPIRATION_MS)); + + // apply sample 5 times, sample should not expire + auto runs(5); + while (runs--) + { + desc_gate.ApplySample(CreateService("service1"), eCAL::tl_none); + std::this_thread::sleep_for(std::chrono::milliseconds(DESCGATE_EXPIRATION_MS / 2)); + + EXPECT_EQ(1, desc_gate.GetServices().size()); + } + + // now let the sample expire + std::this_thread::sleep_for(std::chrono::milliseconds(DESCGATE_EXPIRATION_MS)); + + // sample should be expired + EXPECT_EQ(0, desc_gate.GetServices().size()); +} + +TEST(core_cpp_descgate, ManyService) +{ + eCAL::CDescGate desc_gate(std::chrono::milliseconds(DESCGATE_EXPIRATION_MS)); + + constexpr int num_service(1000); + for (auto service = 0; service < num_service; ++service) + { + // create registration sample for service-xx + desc_gate.ApplySample(CreateService("service" + std::to_string(service)), eCAL::tl_none); + } + + // map should contain num_service samples + EXPECT_EQ(num_service, desc_gate.GetServices().size()); + + // now let the samples expire + std::this_thread::sleep_for(std::chrono::milliseconds(DESCGATE_EXPIRATION_MS)); + + // samples should be expired + EXPECT_EQ(0, desc_gate.GetServices().size()); +} + +TEST(core_cpp_descgate, ClientExpiration) +{ + eCAL::CDescGate desc_gate(std::chrono::milliseconds(DESCGATE_EXPIRATION_MS)); + + // apply sample 5 times, sample should not expire + auto runs(5); + while (runs--) + { + desc_gate.ApplySample(CreateClient("client1"), eCAL::tl_none); + std::this_thread::sleep_for(std::chrono::milliseconds(DESCGATE_EXPIRATION_MS / 2)); + + EXPECT_EQ(1, desc_gate.GetClients().size()); + } + + // now let the sample expire + std::this_thread::sleep_for(std::chrono::milliseconds(DESCGATE_EXPIRATION_MS)); + + // sample should be expired + EXPECT_EQ(0, desc_gate.GetClients().size()); +} + +TEST(core_cpp_descgate, ManyClient) +{ + eCAL::CDescGate desc_gate(std::chrono::milliseconds(DESCGATE_EXPIRATION_MS)); - auto& ecal_reg_sample_topic = reg_sample.topic; - ecal_reg_sample_topic.tname = "foo"; - ecal_reg_sample_topic.tid = "12345"; + constexpr int num_client(1000); + for (auto client = 0; client < num_client; ++client) + { + // create registration sample for client-xx + desc_gate.ApplySample(CreateClient("client" + std::to_string(client)), eCAL::tl_none); + } - desc_gate->ApplySample(reg_sample, eCAL::tl_none); + // map should contain num_client samples + EXPECT_EQ(num_client, desc_gate.GetClients().size()); - pub_map = desc_gate->GetPublisher(); - EXPECT_EQ(0, pub_map.size()); + // now let the samples expire + std::this_thread::sleep_for(std::chrono::milliseconds(DESCGATE_EXPIRATION_MS)); -#endif + // samples should be expired + EXPECT_EQ(0, desc_gate.GetClients().size()); } From f4b7753b1c312f8c6d863570f4a4d6acec1e86fb Mon Sep 17 00:00:00 2001 From: rex-schilasky <49162693+rex-schilasky@users.noreply.github.com> Date: Tue, 16 Apr 2024 21:04:37 +0200 Subject: [PATCH 15/27] topic_id, service_id now uint64_t --- ecal/core/include/ecal/ecal_util.h | 4 +- ecal/core/src/ecal_descgate.cpp | 26 +++++----- ecal/core/src/ecal_descgate.h | 18 +++---- .../string/minimal_snd/src/minimal_snd.cpp | 47 ++++++------------- 4 files changed, 39 insertions(+), 56 deletions(-) diff --git a/ecal/core/include/ecal/ecal_util.h b/ecal/core/include/ecal/ecal_util.h index 9cec991cf8..dff84bcc16 100644 --- a/ecal/core/include/ecal/ecal_util.h +++ b/ecal/core/include/ecal/ecal_util.h @@ -51,14 +51,14 @@ namespace eCAL struct SQualityTopicInfo { - std::string id; + std::uint64_t id; SDataTypeInformation info; DescQualityFlags quality = DescQualityFlags::NO_QUALITY; }; struct SQualityServiceInfo { - std::string id; + std::uint64_t id; SServiceMethodInformation info; DescQualityFlags request_quality = DescQualityFlags::NO_QUALITY; DescQualityFlags response_quality = DescQualityFlags::NO_QUALITY; diff --git a/ecal/core/src/ecal_descgate.cpp b/ecal/core/src/ecal_descgate.cpp index 5f6004ea83..a4cf024f54 100644 --- a/ecal/core/src/ecal_descgate.cpp +++ b/ecal/core/src/ecal_descgate.cpp @@ -121,12 +121,12 @@ namespace eCAL response_type.name = method.resp_type; response_type.descriptor = method.resp_desc; - ApplyServiceDescription(m_service_info_map, sample_.service.sname, sample_.service.sid, method.mname, request_type, response_type, GetDataTypeInfoQuality(request_type, true), GetDataTypeInfoQuality(response_type, true)); + ApplyServiceDescription(m_service_info_map, sample_.service.sname, method.mname, std::stoull(sample_.service.sid), request_type, response_type, GetDataTypeInfoQuality(request_type, true), GetDataTypeInfoQuality(response_type, true)); } } break; case bct_unreg_service: - RemServiceDescription(m_service_info_map, sample_.service.sname, sample_.service.sid); + RemServiceDescription(m_service_info_map, sample_.service.sname, std::stoull(sample_.service.sid)); break; case bct_reg_client: for (const auto& method : sample_.client.methods) @@ -139,23 +139,23 @@ namespace eCAL response_type.name = method.resp_type; response_type.descriptor = method.resp_desc; - ApplyServiceDescription(m_client_info_map, sample_.client.sname, sample_.client.sid, method.mname, request_type, response_type, GetDataTypeInfoQuality(request_type, false), GetDataTypeInfoQuality(response_type, false)); + ApplyServiceDescription(m_client_info_map, sample_.client.sname, method.mname, std::stoull(sample_.client.sid), request_type, response_type, GetDataTypeInfoQuality(request_type, false), GetDataTypeInfoQuality(response_type, false)); } break; case bct_unreg_client: - RemServiceDescription(m_client_info_map, sample_.client.sname, sample_.client.sid); + RemServiceDescription(m_client_info_map, sample_.client.sname, std::stoull(sample_.client.sid)); break; case bct_reg_publisher: - ApplyTopicDescription(m_publisher_info_map, sample_.topic.tname, sample_.topic.tid, sample_.topic.tdatatype, GetDataTypeInfoQuality(sample_.topic.tdatatype, true)); + ApplyTopicDescription(m_publisher_info_map, sample_.topic.tname, std::stoull(sample_.topic.tid), sample_.topic.tdatatype, GetDataTypeInfoQuality(sample_.topic.tdatatype, true)); break; case bct_unreg_publisher: - RemTopicDescription(m_publisher_info_map, sample_.topic.tname, sample_.topic.tid); + RemTopicDescription(m_publisher_info_map, sample_.topic.tname, std::stoull(sample_.topic.tid)); break; case bct_reg_subscriber: - ApplyTopicDescription(m_subscriber_info_map, sample_.topic.tname, sample_.topic.tid, sample_.topic.tdatatype, GetDataTypeInfoQuality(sample_.topic.tdatatype, false)); + ApplyTopicDescription(m_subscriber_info_map, sample_.topic.tname, std::stoull(sample_.topic.tid), sample_.topic.tdatatype, GetDataTypeInfoQuality(sample_.topic.tdatatype, false)); break; case bct_unreg_subscriber: - RemTopicDescription(m_subscriber_info_map, sample_.topic.tname, sample_.topic.tid); + RemTopicDescription(m_subscriber_info_map, sample_.topic.tname, std::stoull(sample_.topic.tid)); break; default: { @@ -167,7 +167,7 @@ namespace eCAL void CDescGate::ApplyTopicDescription(SQualityTopicIdMap& topic_info_map_, const std::string& topic_name_, - const std::string& topic_id_, + const std::uint64_t& topic_id_, const SDataTypeInformation& topic_info_, const Util::DescQualityFlags topic_quality_) { @@ -183,7 +183,7 @@ namespace eCAL (*topic_info_map_.map)[topic_info_key] = topic_quality_info; } - void CDescGate::RemTopicDescription(SQualityTopicIdMap& topic_info_map_, const std::string& topic_name_, const std::string& topic_id_) + void CDescGate::RemTopicDescription(SQualityTopicIdMap& topic_info_map_, const std::string& topic_name_, const std::uint64_t& topic_id_) { const std::unique_lock lock(topic_info_map_.mtx); topic_info_map_.map->remove_deprecated(); @@ -192,14 +192,14 @@ namespace eCAL void CDescGate::ApplyServiceDescription(SQualityServiceIdMap& service_method_info_map_, const std::string& service_name_, - const std::string& service_id_, const std::string& method_name_, + const std::uint64_t& service_id_, const SDataTypeInformation& request_type_information_, const SDataTypeInformation& response_type_information_, const Util::DescQualityFlags request_type_quality_, const Util::DescQualityFlags response_type_quality_) { - const auto service_method_info_key = SServiceIdKey{ service_name_, service_id_, method_name_ }; + const auto service_method_info_key = SServiceIdKey{ service_name_, method_name_, service_id_}; Util::SQualityServiceInfo service_quality_info; service_quality_info.id = service_id_; @@ -213,7 +213,7 @@ namespace eCAL (*service_method_info_map_.map)[service_method_info_key] = service_quality_info; } - void CDescGate::RemServiceDescription(SQualityServiceIdMap& service_method_info_map_, const std::string& service_name_, const std::string& service_id_) + void CDescGate::RemServiceDescription(SQualityServiceIdMap& service_method_info_map_, const std::string& service_name_, const std::uint64_t& service_id_) { std::list service_method_infos_to_remove; diff --git a/ecal/core/src/ecal_descgate.h b/ecal/core/src/ecal_descgate.h index 9e663762aa..73deada2d8 100644 --- a/ecal/core/src/ecal_descgate.h +++ b/ecal/core/src/ecal_descgate.h @@ -38,8 +38,8 @@ namespace eCAL { struct STopicIdKey { - std::string topic_name; - std::string topic_id; + std::string topic_name; + std::uint64_t topic_id; bool operator<(const STopicIdKey& other) const { @@ -51,9 +51,9 @@ namespace eCAL struct SServiceIdKey { - std::string service_name; - std::string service_id; - std::string method_name; + std::string service_name; + std::string method_name; + std::uint64_t service_id; bool operator<(const SServiceIdKey& other) const { @@ -126,18 +126,18 @@ namespace eCAL void ApplyTopicDescription(SQualityTopicIdMap& topic_info_map_, const std::string& topic_name_, - const std::string& topic_id_, + const std::uint64_t& topic_id_, const SDataTypeInformation& topic_info_, Util::DescQualityFlags topic_quality_); void RemTopicDescription(SQualityTopicIdMap& topic_info_map_, const std::string& topic_name_, - const std::string& topic_id_); + const std::uint64_t& topic_id_); void ApplyServiceDescription(SQualityServiceIdMap& service_method_info_map_, const std::string& service_name_, - const std::string& service_id_, const std::string& method_name_, + const std::uint64_t& service_id_, const SDataTypeInformation& request_type_information_, const SDataTypeInformation& response_type_information_, Util::DescQualityFlags request_type_quality_, @@ -145,6 +145,6 @@ namespace eCAL void RemServiceDescription(SQualityServiceIdMap& service_method_info_map_, const std::string& service_name_, - const std::string& service_id_); + const std::uint64_t& service_id_); }; } diff --git a/ecal/samples/cpp/pubsub/string/minimal_snd/src/minimal_snd.cpp b/ecal/samples/cpp/pubsub/string/minimal_snd/src/minimal_snd.cpp index 85889a61c1..7264f79061 100644 --- a/ecal/samples/cpp/pubsub/string/minimal_snd/src/minimal_snd.cpp +++ b/ecal/samples/cpp/pubsub/string/minimal_snd/src/minimal_snd.cpp @@ -21,42 +21,25 @@ #include #include -#include +#include -int main(int argc, char **argv) +class CDescGate { - std::cout << "-------------------------------" << std::endl; - std::cout << " HELLO WORLD SENDER" << std::endl; - std::cout << "-------------------------------" << std::endl; - - // initialize eCAL API - eCAL::Initialize(argc, argv, "minimal_snd"); - - // publisher for topic "Hello" - eCAL::string::CPublisher pub("Hello"); - - // set some attributes - pub.SetAttribute("Hello", "World"); - pub.SetAttribute("Hallo", "Welt"); - - // send updates - int cnt = 0; - while (eCAL::Ok()) +public: + CDescGate(const std::chrono::milliseconds& exp_timeout_) { - // build string - std::stringstream snd_content; - snd_content << "Hello World" << " (" << ++cnt << ")"; - - // send content - pub.Send(snd_content.str(), cnt); - std::cout << "Sent \"" << snd_content.str() << "\"" << std::endl; - - // sleep 10 ms - eCAL::Process::SleepMS(10); + std::cout << "Constructor" << std::endl; } + void Foo() + { + std::cout << "Foo" << std::endl; + } +}; - // finalize eCAL API - eCAL::Finalize(); - +int main(int argc, char **argv) +{ + long long time_ms(5000); + CDescGate desc_gate(std::chrono::milliseconds(time_ms)); + desc_gate.Foo(); return(0); } From ef291752ef2f17a25274777dd1be3b6c327dc837 Mon Sep 17 00:00:00 2001 From: rex-schilasky <49162693+rex-schilasky@users.noreply.github.com> Date: Tue, 16 Apr 2024 21:22:48 +0200 Subject: [PATCH 16/27] minimal send sample reverted --- .../string/minimal_snd/src/minimal_snd.cpp | 47 +++++++++++++------ 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/ecal/samples/cpp/pubsub/string/minimal_snd/src/minimal_snd.cpp b/ecal/samples/cpp/pubsub/string/minimal_snd/src/minimal_snd.cpp index 7264f79061..85889a61c1 100644 --- a/ecal/samples/cpp/pubsub/string/minimal_snd/src/minimal_snd.cpp +++ b/ecal/samples/cpp/pubsub/string/minimal_snd/src/minimal_snd.cpp @@ -21,25 +21,42 @@ #include #include -#include +#include -class CDescGate +int main(int argc, char **argv) { -public: - CDescGate(const std::chrono::milliseconds& exp_timeout_) - { - std::cout << "Constructor" << std::endl; - } - void Foo() + std::cout << "-------------------------------" << std::endl; + std::cout << " HELLO WORLD SENDER" << std::endl; + std::cout << "-------------------------------" << std::endl; + + // initialize eCAL API + eCAL::Initialize(argc, argv, "minimal_snd"); + + // publisher for topic "Hello" + eCAL::string::CPublisher pub("Hello"); + + // set some attributes + pub.SetAttribute("Hello", "World"); + pub.SetAttribute("Hallo", "Welt"); + + // send updates + int cnt = 0; + while (eCAL::Ok()) { - std::cout << "Foo" << std::endl; + // build string + std::stringstream snd_content; + snd_content << "Hello World" << " (" << ++cnt << ")"; + + // send content + pub.Send(snd_content.str(), cnt); + std::cout << "Sent \"" << snd_content.str() << "\"" << std::endl; + + // sleep 10 ms + eCAL::Process::SleepMS(10); } -}; -int main(int argc, char **argv) -{ - long long time_ms(5000); - CDescGate desc_gate(std::chrono::milliseconds(time_ms)); - desc_gate.Foo(); + // finalize eCAL API + eCAL::Finalize(); + return(0); } From d232e1341ba7a69becfe040c08cccba9e9d7b5cc Mon Sep 17 00:00:00 2001 From: rex-schilasky <49162693+rex-schilasky@users.noreply.github.com> Date: Wed, 17 Apr 2024 07:39:40 +0200 Subject: [PATCH 17/27] desc_gate test fixed --- .../cpp/descgate_test/src/getpublisher.cpp | 91 ++++++++++++++----- 1 file changed, 69 insertions(+), 22 deletions(-) diff --git a/ecal/tests/cpp/descgate_test/src/getpublisher.cpp b/ecal/tests/cpp/descgate_test/src/getpublisher.cpp index 86dc0ec262..8902b23dc9 100644 --- a/ecal/tests/cpp/descgate_test/src/getpublisher.cpp +++ b/ecal/tests/cpp/descgate_test/src/getpublisher.cpp @@ -28,36 +28,36 @@ namespace { - eCAL::Registration::Sample CreatePublisher(const std::string& topic_name_) + eCAL::Registration::Sample CreatePublisher(const std::string& topic_name_, std::uint64_t topic_id_) { eCAL::Registration::Sample reg_sample; reg_sample.cmd_type = eCAL::bct_reg_publisher; reg_sample.topic.tname = topic_name_; - reg_sample.topic.tid = topic_name_ + "-id"; + reg_sample.topic.tid = topic_id_; reg_sample.topic.tdatatype.name = topic_name_ + "-tdatatype.name"; reg_sample.topic.tdatatype.encoding = topic_name_ + "-tdatatype.encoding"; reg_sample.topic.tdatatype.descriptor = topic_name_ + "-tdatatype.descriptor"; return reg_sample; } - eCAL::Registration::Sample CreateSubscriber(const std::string& topic_name_) + eCAL::Registration::Sample CreateSubscriber(const std::string& topic_name_, std::uint64_t topic_id_) { eCAL::Registration::Sample reg_sample; reg_sample.cmd_type = eCAL::bct_reg_subscriber; reg_sample.topic.tname = topic_name_; - reg_sample.topic.tid = topic_name_ + "-id"; + reg_sample.topic.tid = topic_id_; reg_sample.topic.tdatatype.name = topic_name_ + "-tdatatype.name"; reg_sample.topic.tdatatype.encoding = topic_name_ + "-tdatatype.encoding"; reg_sample.topic.tdatatype.descriptor = topic_name_ + "-tdatatype.descriptor"; return reg_sample; } - eCAL::Registration::Sample CreateService(const std::string& service_name_) + eCAL::Registration::Sample CreateService(const std::string& service_name_, std::uint64_t service_id_) { eCAL::Registration::Sample reg_sample; reg_sample.cmd_type = eCAL::bct_reg_service; reg_sample.service.sname = service_name_; - reg_sample.service.sid = service_name_ + "-id"; + reg_sample.service.sid = service_id_; eCAL::Service::Method method; method.mname = "method_name"; @@ -65,12 +65,12 @@ namespace return reg_sample; } - eCAL::Registration::Sample CreateClient(const std::string& client_name_) + eCAL::Registration::Sample CreateClient(const std::string& client_name_, std::uint64_t service_id_) { eCAL::Registration::Sample reg_sample; reg_sample.cmd_type = eCAL::bct_reg_client; reg_sample.client.sname = client_name_; - reg_sample.client.sid = client_name_ + "-id"; + reg_sample.client.sid = service_id_; eCAL::Service::Method method; method.mname = "method_name"; @@ -87,7 +87,7 @@ TEST(core_cpp_descgate, PublisherExpiration) auto runs(5); while (runs--) { - desc_gate.ApplySample(CreatePublisher("pub1"), eCAL::tl_none); + desc_gate.ApplySample(CreatePublisher("pub1", 1), eCAL::tl_none); std::this_thread::sleep_for(std::chrono::milliseconds(DESCGATE_EXPIRATION_MS / 2)); EXPECT_EQ(1, desc_gate.GetPublisher().size()); @@ -105,10 +105,10 @@ TEST(core_cpp_descgate, PublisherQualities) eCAL::CDescGate desc_gate(std::chrono::milliseconds(DESCGATE_EXPIRATION_MS)); // create and apply publisher pub1 - desc_gate.ApplySample(CreatePublisher("pub1"), eCAL::tl_none); + desc_gate.ApplySample(CreatePublisher("pub1", 1), eCAL::tl_none); // create and apply publisher pub2 - desc_gate.ApplySample(CreatePublisher("pub2"), eCAL::tl_none); + desc_gate.ApplySample(CreatePublisher("pub2", 2), eCAL::tl_none); // check gate size auto sample_map = desc_gate.GetPublisher(); @@ -116,11 +116,11 @@ TEST(core_cpp_descgate, PublisherQualities) // check pub1 quality { - auto pub_it = sample_map.find({ "pub1", "pub1-id" }); + auto pub_it = sample_map.find({ "pub1", 1 }); EXPECT_NE(pub_it, sample_map.end()); if (pub_it != sample_map.end()) { - EXPECT_EQ("pub1-id", pub_it->second.id); + EXPECT_EQ(1, pub_it->second.id); EXPECT_EQ("pub1-tdatatype.name", pub_it->second.info.name); EXPECT_EQ("pub1-tdatatype.encoding", pub_it->second.info.encoding); EXPECT_EQ("pub1-tdatatype.descriptor", pub_it->second.info.descriptor); @@ -129,11 +129,11 @@ TEST(core_cpp_descgate, PublisherQualities) // check pub2 quality { - auto pub_it = sample_map.find({ "pub2", "pub2-id" }); + auto pub_it = sample_map.find({ "pub2", 2 }); EXPECT_NE(pub_it, sample_map.end()); if (pub_it != sample_map.end()) { - EXPECT_EQ("pub2-id", pub_it->second.id); + EXPECT_EQ(2, pub_it->second.id); EXPECT_EQ("pub2-tdatatype.name", pub_it->second.info.name); EXPECT_EQ("pub2-tdatatype.encoding", pub_it->second.info.encoding); EXPECT_EQ("pub2-tdatatype.descriptor", pub_it->second.info.descriptor); @@ -155,7 +155,7 @@ TEST(core_cpp_descgate, ManyPublisher) for (auto pub = 0; pub < num_pub; ++pub) { // create registration sample for pub-xx - desc_gate.ApplySample(CreatePublisher("pub" + std::to_string(pub)), eCAL::tl_none); + desc_gate.ApplySample(CreatePublisher("pub" + std::to_string(pub), pub), eCAL::tl_none); } // map should contain num_pub samples @@ -176,7 +176,7 @@ TEST(core_cpp_descgate, SubscriberExpiration) auto runs(5); while (runs--) { - desc_gate.ApplySample(CreateSubscriber("sub1"), eCAL::tl_none); + desc_gate.ApplySample(CreateSubscriber("sub1", 1), eCAL::tl_none); std::this_thread::sleep_for(std::chrono::milliseconds(DESCGATE_EXPIRATION_MS / 2)); EXPECT_EQ(1, desc_gate.GetSubscriber().size()); @@ -189,6 +189,53 @@ TEST(core_cpp_descgate, SubscriberExpiration) EXPECT_EQ(0, desc_gate.GetSubscriber().size()); } +TEST(core_cpp_descgate, SubscriberQualities) +{ + eCAL::CDescGate desc_gate(std::chrono::milliseconds(DESCGATE_EXPIRATION_MS)); + + // create and apply subscriber sub1 + desc_gate.ApplySample(CreateSubscriber("sub1", 1), eCAL::tl_none); + + // create and apply subscriber sub2 + desc_gate.ApplySample(CreateSubscriber("sub2", 2), eCAL::tl_none); + + // check gate size + auto sample_map = desc_gate.GetSubscriber(); + EXPECT_EQ(2, sample_map.size()); + + // check sub1 quality + { + auto sub_it = sample_map.find({ "sub1", 1 }); + EXPECT_NE(sub_it, sample_map.end()); + if (sub_it != sample_map.end()) + { + EXPECT_EQ(1, sub_it->second.id); + EXPECT_EQ("sub1-tdatatype.name", sub_it->second.info.name); + EXPECT_EQ("sub1-tdatatype.encoding", sub_it->second.info.encoding); + EXPECT_EQ("sub1-tdatatype.descriptor", sub_it->second.info.descriptor); + } + } + + // check sub2 quality + { + auto sub_it = sample_map.find({ "sub2", 2 }); + EXPECT_NE(sub_it, sample_map.end()); + if (sub_it != sample_map.end()) + { + EXPECT_EQ(2, sub_it->second.id); + EXPECT_EQ("sub2-tdatatype.name", sub_it->second.info.name); + EXPECT_EQ("sub2-tdatatype.encoding", sub_it->second.info.encoding); + EXPECT_EQ("sub2-tdatatype.descriptor", sub_it->second.info.descriptor); + } + } + + // now let the sample expire + std::this_thread::sleep_for(std::chrono::milliseconds(DESCGATE_EXPIRATION_MS)); + + // sample should be expired + EXPECT_EQ(0, desc_gate.GetSubscriber().size()); +} + TEST(core_cpp_descgate, ManySubscriber) { eCAL::CDescGate desc_gate(std::chrono::milliseconds(DESCGATE_EXPIRATION_MS)); @@ -197,7 +244,7 @@ TEST(core_cpp_descgate, ManySubscriber) for (auto sub = 0; sub < num_sub; ++sub) { // create registration sample for sub-xx - desc_gate.ApplySample(CreateSubscriber("sub" + std::to_string(sub)), eCAL::tl_none); + desc_gate.ApplySample(CreateSubscriber("sub" + std::to_string(sub), sub), eCAL::tl_none); } // map should contain num_sub samples @@ -218,7 +265,7 @@ TEST(core_cpp_descgate, ServiceExpiration) auto runs(5); while (runs--) { - desc_gate.ApplySample(CreateService("service1"), eCAL::tl_none); + desc_gate.ApplySample(CreateService("service1", 1), eCAL::tl_none); std::this_thread::sleep_for(std::chrono::milliseconds(DESCGATE_EXPIRATION_MS / 2)); EXPECT_EQ(1, desc_gate.GetServices().size()); @@ -239,7 +286,7 @@ TEST(core_cpp_descgate, ManyService) for (auto service = 0; service < num_service; ++service) { // create registration sample for service-xx - desc_gate.ApplySample(CreateService("service" + std::to_string(service)), eCAL::tl_none); + desc_gate.ApplySample(CreateService("service" + std::to_string(service), service), eCAL::tl_none); } // map should contain num_service samples @@ -260,7 +307,7 @@ TEST(core_cpp_descgate, ClientExpiration) auto runs(5); while (runs--) { - desc_gate.ApplySample(CreateClient("client1"), eCAL::tl_none); + desc_gate.ApplySample(CreateClient("client1", 1), eCAL::tl_none); std::this_thread::sleep_for(std::chrono::milliseconds(DESCGATE_EXPIRATION_MS / 2)); EXPECT_EQ(1, desc_gate.GetClients().size()); @@ -281,7 +328,7 @@ TEST(core_cpp_descgate, ManyClient) for (auto client = 0; client < num_client; ++client) { // create registration sample for client-xx - desc_gate.ApplySample(CreateClient("client" + std::to_string(client)), eCAL::tl_none); + desc_gate.ApplySample(CreateClient("client" + std::to_string(client), client), eCAL::tl_none); } // map should contain num_client samples From e819830615ec24e9b99dfac80f947cb13bcfeca1 Mon Sep 17 00:00:00 2001 From: rex-schilasky <49162693+rex-schilasky@users.noreply.github.com> Date: Wed, 17 Apr 2024 10:35:51 +0200 Subject: [PATCH 18/27] DescQualityFlags operators added again types introduced for TopicId and ServiceId --- ecal/core/include/ecal/ecal_util.h | 15 ++++++++++++--- ecal/core/src/ecal_descgate.cpp | 8 ++++---- ecal/core/src/ecal_descgate.h | 16 ++++++++-------- 3 files changed, 24 insertions(+), 15 deletions(-) diff --git a/ecal/core/include/ecal/ecal_util.h b/ecal/core/include/ecal/ecal_util.h index dff84bcc16..43095a1e20 100644 --- a/ecal/core/include/ecal/ecal_util.h +++ b/ecal/core/include/ecal/ecal_util.h @@ -47,18 +47,27 @@ namespace eCAL TYPENAME_AVAILABLE = 0x1 << 1, //!< Having a type name available INFO_COMES_FROM_PRODUCER = 0x1 << 0 //!< Info is coming from the producer (like a publisher, service) }; - inline DescQualityFlags& operator|= (DescQualityFlags& a, DescQualityFlags b) { return reinterpret_cast(reinterpret_cast&>(a) |= static_cast>(b)); } + constexpr inline DescQualityFlags operator~ (DescQualityFlags a) { return static_cast( ~static_cast::type>(a) ); } + constexpr inline DescQualityFlags operator| (DescQualityFlags a, DescQualityFlags b) { return static_cast( static_cast::type>(a) | static_cast::type>(b) ); } + constexpr inline DescQualityFlags operator& (DescQualityFlags a, DescQualityFlags b) { return static_cast( static_cast::type>(a) & static_cast::type>(b) ); } + constexpr inline DescQualityFlags operator^ (DescQualityFlags a, DescQualityFlags b) { return static_cast( static_cast::type>(a) ^ static_cast::type>(b) ); } + inline DescQualityFlags& operator|= (DescQualityFlags& a, DescQualityFlags b) { return reinterpret_cast( reinterpret_cast::type&>(a) |= static_cast::type>(b) ); } + inline DescQualityFlags& operator&= (DescQualityFlags& a, DescQualityFlags b) { return reinterpret_cast( reinterpret_cast::type&>(a) &= static_cast::type>(b) ); } + inline DescQualityFlags& operator^= (DescQualityFlags& a, DescQualityFlags b) { return reinterpret_cast( reinterpret_cast::type&>(a) ^= static_cast::type>(b) ); } + + using TopicId = std::uint64_t; struct SQualityTopicInfo { - std::uint64_t id; + TopicId id; SDataTypeInformation info; DescQualityFlags quality = DescQualityFlags::NO_QUALITY; }; + using ServiceId = std::uint64_t; struct SQualityServiceInfo { - std::uint64_t id; + ServiceId id; SServiceMethodInformation info; DescQualityFlags request_quality = DescQualityFlags::NO_QUALITY; DescQualityFlags response_quality = DescQualityFlags::NO_QUALITY; diff --git a/ecal/core/src/ecal_descgate.cpp b/ecal/core/src/ecal_descgate.cpp index a4cf024f54..02684961a4 100644 --- a/ecal/core/src/ecal_descgate.cpp +++ b/ecal/core/src/ecal_descgate.cpp @@ -167,7 +167,7 @@ namespace eCAL void CDescGate::ApplyTopicDescription(SQualityTopicIdMap& topic_info_map_, const std::string& topic_name_, - const std::uint64_t& topic_id_, + const Util::TopicId& topic_id_, const SDataTypeInformation& topic_info_, const Util::DescQualityFlags topic_quality_) { @@ -183,7 +183,7 @@ namespace eCAL (*topic_info_map_.map)[topic_info_key] = topic_quality_info; } - void CDescGate::RemTopicDescription(SQualityTopicIdMap& topic_info_map_, const std::string& topic_name_, const std::uint64_t& topic_id_) + void CDescGate::RemTopicDescription(SQualityTopicIdMap& topic_info_map_, const std::string& topic_name_, const Util::TopicId& topic_id_) { const std::unique_lock lock(topic_info_map_.mtx); topic_info_map_.map->remove_deprecated(); @@ -193,7 +193,7 @@ namespace eCAL void CDescGate::ApplyServiceDescription(SQualityServiceIdMap& service_method_info_map_, const std::string& service_name_, const std::string& method_name_, - const std::uint64_t& service_id_, + const Util::ServiceId& service_id_, const SDataTypeInformation& request_type_information_, const SDataTypeInformation& response_type_information_, const Util::DescQualityFlags request_type_quality_, @@ -213,7 +213,7 @@ namespace eCAL (*service_method_info_map_.map)[service_method_info_key] = service_quality_info; } - void CDescGate::RemServiceDescription(SQualityServiceIdMap& service_method_info_map_, const std::string& service_name_, const std::uint64_t& service_id_) + void CDescGate::RemServiceDescription(SQualityServiceIdMap& service_method_info_map_, const std::string& service_name_, const Util::ServiceId& service_id_) { std::list service_method_infos_to_remove; diff --git a/ecal/core/src/ecal_descgate.h b/ecal/core/src/ecal_descgate.h index 73deada2d8..8ca57344cf 100644 --- a/ecal/core/src/ecal_descgate.h +++ b/ecal/core/src/ecal_descgate.h @@ -39,7 +39,7 @@ namespace eCAL struct STopicIdKey { std::string topic_name; - std::uint64_t topic_id; + Util::TopicId topic_id; bool operator<(const STopicIdKey& other) const { @@ -51,9 +51,9 @@ namespace eCAL struct SServiceIdKey { - std::string service_name; - std::string method_name; - std::uint64_t service_id; + std::string service_name; + std::string method_name; + Util::ServiceId service_id; bool operator<(const SServiceIdKey& other) const { @@ -126,18 +126,18 @@ namespace eCAL void ApplyTopicDescription(SQualityTopicIdMap& topic_info_map_, const std::string& topic_name_, - const std::uint64_t& topic_id_, + const Util::TopicId& topic_id_, const SDataTypeInformation& topic_info_, Util::DescQualityFlags topic_quality_); void RemTopicDescription(SQualityTopicIdMap& topic_info_map_, const std::string& topic_name_, - const std::uint64_t& topic_id_); + const Util::TopicId& topic_id_); void ApplyServiceDescription(SQualityServiceIdMap& service_method_info_map_, const std::string& service_name_, const std::string& method_name_, - const std::uint64_t& service_id_, + const Util::ServiceId& service_id_, const SDataTypeInformation& request_type_information_, const SDataTypeInformation& response_type_information_, Util::DescQualityFlags request_type_quality_, @@ -145,6 +145,6 @@ namespace eCAL void RemServiceDescription(SQualityServiceIdMap& service_method_info_map_, const std::string& service_name_, - const std::uint64_t& service_id_); + const Util::ServiceId& service_id_); }; } From 1897fe6b3005edada5ede96b05bb8b615bda2c4d Mon Sep 17 00:00:00 2001 From: rex-schilasky <49162693+rex-schilasky@users.noreply.github.com> Date: Thu, 18 Apr 2024 09:32:44 +0200 Subject: [PATCH 19/27] descgate getpublisher test corrected --- ecal/tests/cpp/descgate_test/src/getpublisher.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ecal/tests/cpp/descgate_test/src/getpublisher.cpp b/ecal/tests/cpp/descgate_test/src/getpublisher.cpp index 8902b23dc9..e385cd1456 100644 --- a/ecal/tests/cpp/descgate_test/src/getpublisher.cpp +++ b/ecal/tests/cpp/descgate_test/src/getpublisher.cpp @@ -33,7 +33,7 @@ namespace eCAL::Registration::Sample reg_sample; reg_sample.cmd_type = eCAL::bct_reg_publisher; reg_sample.topic.tname = topic_name_; - reg_sample.topic.tid = topic_id_; + reg_sample.topic.tid = std::to_string(topic_id_); reg_sample.topic.tdatatype.name = topic_name_ + "-tdatatype.name"; reg_sample.topic.tdatatype.encoding = topic_name_ + "-tdatatype.encoding"; reg_sample.topic.tdatatype.descriptor = topic_name_ + "-tdatatype.descriptor"; @@ -45,7 +45,7 @@ namespace eCAL::Registration::Sample reg_sample; reg_sample.cmd_type = eCAL::bct_reg_subscriber; reg_sample.topic.tname = topic_name_; - reg_sample.topic.tid = topic_id_; + reg_sample.topic.tid = std::to_string(topic_id_); reg_sample.topic.tdatatype.name = topic_name_ + "-tdatatype.name"; reg_sample.topic.tdatatype.encoding = topic_name_ + "-tdatatype.encoding"; reg_sample.topic.tdatatype.descriptor = topic_name_ + "-tdatatype.descriptor"; @@ -57,7 +57,7 @@ namespace eCAL::Registration::Sample reg_sample; reg_sample.cmd_type = eCAL::bct_reg_service; reg_sample.service.sname = service_name_; - reg_sample.service.sid = service_id_; + reg_sample.service.sid = std::to_string(service_id_); eCAL::Service::Method method; method.mname = "method_name"; @@ -70,7 +70,7 @@ namespace eCAL::Registration::Sample reg_sample; reg_sample.cmd_type = eCAL::bct_reg_client; reg_sample.client.sname = client_name_; - reg_sample.client.sid = service_id_; + reg_sample.client.sid = std::to_string(service_id_); eCAL::Service::Method method; method.mname = "method_name"; From 1df54d12e04711c0bbeb33f85d9d55d9c38f0070 Mon Sep 17 00:00:00 2001 From: rex-schilasky <49162693+rex-schilasky@users.noreply.github.com> Date: Fri, 19 Apr 2024 14:05:02 +0200 Subject: [PATCH 20/27] clang-tidy jitter of 100 ms added to util test timeouts --- ecal/core/include/ecal/ecal_util.h | 4 ++-- ecal/core/src/ecal_util.cpp | 8 ++++---- ecal/tests/CMakeLists.txt | 6 +----- .../cpp/descgate_test/src/getpublisher.cpp | 8 ++++---- ecal/tests/cpp/util_test/CMakeLists.txt | 17 ++++++++++++++--- .../tests/cpp/util_test/src/util_getclients.cpp | 16 ++++++++-------- .../cpp/util_test/src/util_getservices.cpp | 14 +++++++------- ecal/tests/cpp/util_test/src/util_gettopics.cpp | 8 ++++---- ecal/tests/cpp/util_test/src/util_test.cpp | 3 ++- 9 files changed, 46 insertions(+), 38 deletions(-) diff --git a/ecal/core/include/ecal/ecal_util.h b/ecal/core/include/ecal/ecal_util.h index 43095a1e20..d57a660074 100644 --- a/ecal/core/include/ecal/ecal_util.h +++ b/ecal/core/include/ecal/ecal_util.h @@ -59,7 +59,7 @@ namespace eCAL using TopicId = std::uint64_t; struct SQualityTopicInfo { - TopicId id; + TopicId id = 0; SDataTypeInformation info; DescQualityFlags quality = DescQualityFlags::NO_QUALITY; }; @@ -67,7 +67,7 @@ namespace eCAL using ServiceId = std::uint64_t; struct SQualityServiceInfo { - ServiceId id; + ServiceId id = 0; SServiceMethodInformation info; DescQualityFlags request_quality = DescQualityFlags::NO_QUALITY; DescQualityFlags response_quality = DescQualityFlags::NO_QUALITY; diff --git a/ecal/core/src/ecal_util.cpp b/ecal/core/src/ecal_util.cpp index 96ce442663..253e0fcec5 100644 --- a/ecal/core/src/ecal_util.cpp +++ b/ecal/core/src/ecal_util.cpp @@ -484,7 +484,7 @@ namespace eCAL bool GetServiceTypeNames(const std::string& service_name_, const std::string& method_name_, std::string& req_type_, std::string& resp_type_) { - std::vector service_method_info_vec = GetQualityServiceInfoVec(service_name_, method_name_, GetServices()); + const std::vector service_method_info_vec = GetQualityServiceInfoVec(service_name_, method_name_, GetServices()); const SServiceMethodInformation service_method_info = GetHighestQualityServiceMethodInformation(service_method_info_vec); req_type_ = service_method_info.request_type.name; @@ -495,7 +495,7 @@ namespace eCAL bool GetServiceDescription(const std::string& service_name_, const std::string& method_name_, std::string& req_desc_, std::string& resp_desc_) { - std::vector service_method_info_vec = GetQualityServiceInfoVec(service_name_, method_name_, GetServices()); + const std::vector service_method_info_vec = GetQualityServiceInfoVec(service_name_, method_name_, GetServices()); const SServiceMethodInformation service_method_info = GetHighestQualityServiceMethodInformation(service_method_info_vec); req_desc_ = service_method_info.request_type.descriptor; @@ -547,7 +547,7 @@ namespace eCAL bool GetClientTypeNames(const std::string& client_name_, const std::string& method_name_, std::string& req_type_, std::string& resp_type_) { - std::vector service_method_info_vec = GetQualityServiceInfoVec(client_name_, method_name_, GetClients()); + const std::vector service_method_info_vec = GetQualityServiceInfoVec(client_name_, method_name_, GetClients()); const SServiceMethodInformation service_method_info = GetHighestQualityServiceMethodInformation(service_method_info_vec); req_type_ = service_method_info.request_type.name; @@ -558,7 +558,7 @@ namespace eCAL bool GetClientDescription(const std::string& client_name_, const std::string& method_name_, std::string& req_desc_, std::string& resp_desc_) { - std::vector service_method_info_vec = GetQualityServiceInfoVec(client_name_, method_name_, GetClients()); + const std::vector service_method_info_vec = GetQualityServiceInfoVec(client_name_, method_name_, GetClients()); const SServiceMethodInformation service_method_info = GetHighestQualityServiceMethodInformation(service_method_info_vec); req_desc_ = service_method_info.request_type.descriptor; diff --git a/ecal/tests/CMakeLists.txt b/ecal/tests/CMakeLists.txt index 36a7eaf1c1..1fd288da16 100644 --- a/ecal/tests/CMakeLists.txt +++ b/ecal/tests/CMakeLists.txt @@ -30,14 +30,10 @@ add_subdirectory(cpp/core_test) add_subdirectory(cpp/descgate_test) -if(ECAL_CORE_REGISTRATION AND ECAL_CORE_PUBLISHER) +if(ECAL_CORE_REGISTRATION) add_subdirectory(cpp/util_test) endif() - - - - add_subdirectory(cpp/event_test) add_subdirectory(cpp/expmap_test) add_subdirectory(cpp/serialization_test) diff --git a/ecal/tests/cpp/descgate_test/src/getpublisher.cpp b/ecal/tests/cpp/descgate_test/src/getpublisher.cpp index e385cd1456..6e6104cead 100644 --- a/ecal/tests/cpp/descgate_test/src/getpublisher.cpp +++ b/ecal/tests/cpp/descgate_test/src/getpublisher.cpp @@ -85,7 +85,7 @@ TEST(core_cpp_descgate, PublisherExpiration) // apply sample 5 times, sample should not expire auto runs(5); - while (runs--) + while ((runs--) != 0) { desc_gate.ApplySample(CreatePublisher("pub1", 1), eCAL::tl_none); std::this_thread::sleep_for(std::chrono::milliseconds(DESCGATE_EXPIRATION_MS / 2)); @@ -174,7 +174,7 @@ TEST(core_cpp_descgate, SubscriberExpiration) // apply sample 5 times, sample should not expire auto runs(5); - while (runs--) + while ((runs--) != 0) { desc_gate.ApplySample(CreateSubscriber("sub1", 1), eCAL::tl_none); std::this_thread::sleep_for(std::chrono::milliseconds(DESCGATE_EXPIRATION_MS / 2)); @@ -263,7 +263,7 @@ TEST(core_cpp_descgate, ServiceExpiration) // apply sample 5 times, sample should not expire auto runs(5); - while (runs--) + while ((runs--) != 0) { desc_gate.ApplySample(CreateService("service1", 1), eCAL::tl_none); std::this_thread::sleep_for(std::chrono::milliseconds(DESCGATE_EXPIRATION_MS / 2)); @@ -305,7 +305,7 @@ TEST(core_cpp_descgate, ClientExpiration) // apply sample 5 times, sample should not expire auto runs(5); - while (runs--) + while ((runs--) != 0) { desc_gate.ApplySample(CreateClient("client1", 1), eCAL::tl_none); std::this_thread::sleep_for(std::chrono::milliseconds(DESCGATE_EXPIRATION_MS / 2)); diff --git a/ecal/tests/cpp/util_test/CMakeLists.txt b/ecal/tests/cpp/util_test/CMakeLists.txt index 0baf7de422..4d39f66d1d 100644 --- a/ecal/tests/cpp/util_test/CMakeLists.txt +++ b/ecal/tests/cpp/util_test/CMakeLists.txt @@ -21,11 +21,22 @@ project(test_util) find_package(Threads REQUIRED) find_package(GTest REQUIRED) +if(ECAL_CORE_PUBLISHER AND ECAL_CORE_SUBSCRIBER) + set(util_test_topics_src + src/util_gettopics.cpp + ) +endif() + +if(ECAL_CORE_SERVICE) + set(util_test_service_src + src/util_getclients.cpp + src/util_getservices.cpp + ) +endif() set(util_test_src - src/util_getclients.cpp - src/util_getservices.cpp - src/util_gettopics.cpp + ${util_test_topics_src} + ${util_test_service_src} src/util_test.cpp ) diff --git a/ecal/tests/cpp/util_test/src/util_getclients.cpp b/ecal/tests/cpp/util_test/src/util_getclients.cpp index 3a7543d7e6..dbb0f872a3 100644 --- a/ecal/tests/cpp/util_test/src/util_getclients.cpp +++ b/ecal/tests/cpp/util_test/src/util_getclients.cpp @@ -23,8 +23,8 @@ #include enum { - CMN_MONITORING_TIMEOUT = 5000, - CMN_REGISTRATION_REFRESH = 1000 + CMN_MONITORING_TIMEOUT_MS = (5000 + 100), + CMN_REGISTRATION_REFRESH_MS = (1000 + 100) }; TEST(core_cpp_util, ClientExpiration) @@ -42,7 +42,7 @@ TEST(core_cpp_util, ClientExpiration) service_method_info.request_type.descriptor = "foo::req_desc"; service_method_info.response_type.name = "foo::resp_type"; service_method_info.response_type.descriptor = "foo::resp_desc"; - eCAL::CServiceClient client("foo::service", { {"foo::method", service_method_info} }); + const eCAL::CServiceClient client("foo::service", { {"foo::method", service_method_info} }); // get all clients eCAL::Util::GetClients(client_info_map); @@ -61,7 +61,7 @@ TEST(core_cpp_util, ClientExpiration) } // let's wait a monitoring timeout long - eCAL::Process::SleepMS(CMN_MONITORING_TIMEOUT); + eCAL::Process::SleepMS(CMN_MONITORING_TIMEOUT_MS); // get all clients again, client should not be expired eCAL::Util::GetClients(client_info_map); @@ -71,7 +71,7 @@ TEST(core_cpp_util, ClientExpiration) } // let's unregister - eCAL::Process::SleepMS(CMN_REGISTRATION_REFRESH); + eCAL::Process::SleepMS(CMN_REGISTRATION_REFRESH_MS); // get all clients again, all clients // should be removed from the map @@ -139,7 +139,7 @@ TEST(core_cpp_util, ClientEqualQualities) EXPECT_EQ(client_info_map.size(), 1); // let's wait a monitoring timeout long - eCAL::Process::SleepMS(CMN_MONITORING_TIMEOUT); + eCAL::Process::SleepMS(CMN_MONITORING_TIMEOUT_MS); // get all clients again, clients should not be expired eCAL::Util::GetClients(client_info_map); @@ -160,7 +160,7 @@ TEST(core_cpp_util, ClientEqualQualities) } // let's unregister - eCAL::Process::SleepMS(CMN_REGISTRATION_REFRESH); + eCAL::Process::SleepMS(CMN_REGISTRATION_REFRESH_MS); // get all clients again, all clients // should be removed from the map @@ -228,7 +228,7 @@ TEST(core_cpp_util, ClientDifferentQualities) } // let's unregister - eCAL::Process::SleepMS(CMN_REGISTRATION_REFRESH); + eCAL::Process::SleepMS(CMN_REGISTRATION_REFRESH_MS); // get all clients again, all clients // should be removed from the map diff --git a/ecal/tests/cpp/util_test/src/util_getservices.cpp b/ecal/tests/cpp/util_test/src/util_getservices.cpp index 03a325589c..5d497dd195 100644 --- a/ecal/tests/cpp/util_test/src/util_getservices.cpp +++ b/ecal/tests/cpp/util_test/src/util_getservices.cpp @@ -23,8 +23,8 @@ #include enum { - CMN_MONITORING_TIMEOUT = 5000, - CMN_REGISTRATION_REFRESH = 1000 + CMN_MONITORING_TIMEOUT_MS = (5000 + 100), + CMN_REGISTRATION_REFRESH_MS = (1000 + 100) }; TEST(core_cpp_util, ServiceExpiration) @@ -57,7 +57,7 @@ TEST(core_cpp_util, ServiceExpiration) } // let's wait a monitoring timeout long - eCAL::Process::SleepMS(CMN_MONITORING_TIMEOUT); + eCAL::Process::SleepMS(CMN_MONITORING_TIMEOUT_MS); // get all services again, service should not be expired eCAL::Util::GetServices(service_info_map); @@ -67,7 +67,7 @@ TEST(core_cpp_util, ServiceExpiration) } // let's unregister - eCAL::Process::SleepMS(CMN_REGISTRATION_REFRESH); + eCAL::Process::SleepMS(CMN_REGISTRATION_REFRESH_MS); // get all services again, all services // should be removed from the map @@ -127,7 +127,7 @@ TEST(core_cpp_util, ServiceEqualQualities) EXPECT_EQ(service_info_map.size(), 1); // let's wait a monitoring timeout long - eCAL::Process::SleepMS(CMN_MONITORING_TIMEOUT); + eCAL::Process::SleepMS(CMN_MONITORING_TIMEOUT_MS); // get all services again, services should not be expired eCAL::Util::GetServices(service_info_map); @@ -148,7 +148,7 @@ TEST(core_cpp_util, ServiceEqualQualities) } // let's unregister - eCAL::Process::SleepMS(CMN_REGISTRATION_REFRESH); + eCAL::Process::SleepMS(CMN_REGISTRATION_REFRESH_MS); // get all services again, all services // should be removed from the map @@ -208,7 +208,7 @@ TEST(core_cpp_util, ServiceDifferentQualities) } // let's unregister - eCAL::Process::SleepMS(CMN_REGISTRATION_REFRESH); + eCAL::Process::SleepMS(CMN_REGISTRATION_REFRESH_MS); // get all services again, all services // should be removed from the map diff --git a/ecal/tests/cpp/util_test/src/util_gettopics.cpp b/ecal/tests/cpp/util_test/src/util_gettopics.cpp index 7e6af479ad..2dd162b864 100644 --- a/ecal/tests/cpp/util_test/src/util_gettopics.cpp +++ b/ecal/tests/cpp/util_test/src/util_gettopics.cpp @@ -26,8 +26,8 @@ #include enum { - CMN_MONITORING_TIMEOUT = 5000, - CMN_REGISTRATION_REFRESH = 1000 + CMN_MONITORING_TIMEOUT_MS = (5000 + 100), + CMN_REGISTRATION_REFRESH_MS = (1000 + 100) }; TEST(core_cpp_util, GetTopics) @@ -81,7 +81,7 @@ TEST(core_cpp_util, GetTopics) } // wait a monitoring timeout long, - eCAL::Process::SleepMS(CMN_MONITORING_TIMEOUT); + eCAL::Process::SleepMS(CMN_MONITORING_TIMEOUT_MS); // the topics should not be expired eCAL::Util::GetTopics(topic_info_map); @@ -112,7 +112,7 @@ TEST(core_cpp_util, GetTopics) } // let's unregister - eCAL::Process::SleepMS(CMN_REGISTRATION_REFRESH); + eCAL::Process::SleepMS(CMN_REGISTRATION_REFRESH_MS); // get all topics again, now all topics // should be removed from the map diff --git a/ecal/tests/cpp/util_test/src/util_test.cpp b/ecal/tests/cpp/util_test/src/util_test.cpp index d631066fb1..abaf84d48f 100644 --- a/ecal/tests/cpp/util_test/src/util_test.cpp +++ b/ecal/tests/cpp/util_test/src/util_test.cpp @@ -24,7 +24,8 @@ #include -namespace { +namespace +{ void TestCombinedTopicEncodingAndType(const std::string& encoding, const std::string& type, const std::string& expected_result) { auto combined = eCAL::Util::CombinedTopicEncodingAndType(encoding, type); From 9749d722c10e90f7e785eeb13f1381e6186abc71 Mon Sep 17 00:00:00 2001 From: rex-schilasky <49162693+rex-schilasky@users.noreply.github.com> Date: Mon, 22 Apr 2024 15:26:56 +0200 Subject: [PATCH 21/27] CDescGate::GetPublisher -> CDescGate::GetPublishers, CDescGate::GetSubscriber -> CDescGate::GetSubscribers static functions ApplyTopicDescription, RemTopicDescription, ApplyServiceDescription, RemServiceDescription unique_ptr map --- ecal/core/src/ecal_descgate.cpp | 34 ++++----- ecal/core/src/ecal_descgate.h | 72 +++++++++---------- ecal/core/src/ecal_util.cpp | 8 +-- .../cpp/descgate_test/src/getpublisher.cpp | 24 +++---- 4 files changed, 66 insertions(+), 72 deletions(-) diff --git a/ecal/core/src/ecal_descgate.cpp b/ecal/core/src/ecal_descgate.cpp index 02684961a4..31e76d9a92 100644 --- a/ecal/core/src/ecal_descgate.cpp +++ b/ecal/core/src/ecal_descgate.cpp @@ -52,12 +52,12 @@ namespace eCAL } CDescGate::~CDescGate() = default; - QualityTopicIdMap CDescGate::GetPublisher() + QualityTopicIdMap CDescGate::GetPublishers() { return GetTopics(m_publisher_info_map); } - QualityTopicIdMap CDescGate::GetSubscriber() + QualityTopicIdMap CDescGate::GetSubscribers() { return GetTopics(m_subscriber_info_map); } @@ -72,28 +72,28 @@ namespace eCAL return GetServices(m_client_info_map); } - QualityTopicIdMap CDescGate::GetTopics(const SQualityTopicIdMap& topic_map_) + QualityTopicIdMap CDescGate::GetTopics(SQualityTopicIdMap& topic_map_) { QualityTopicIdMap map; const std::lock_guard lock(topic_map_.mtx); - topic_map_.map->remove_deprecated(); + topic_map_.map.remove_deprecated(); - for (const auto& topic_map_it : (*topic_map_.map)) + for (const auto& topic_map_it : topic_map_.map) { map.emplace(topic_map_it.first, topic_map_it.second); } return map; } - QualityServiceIdMap CDescGate::GetServices(const SQualityServiceIdMap& service_method_info_map_) + QualityServiceIdMap CDescGate::GetServices(SQualityServiceIdMap& service_method_info_map_) { QualityServiceIdMap map; const std::lock_guard lock(service_method_info_map_.mtx); - service_method_info_map_.map->remove_deprecated(); + service_method_info_map_.map.remove_deprecated(); - for (const auto& service_method_info_map_it : (*service_method_info_map_.map)) + for (const auto& service_method_info_map_it : service_method_info_map_.map) { map.emplace(service_method_info_map_it.first, service_method_info_map_it.second); } @@ -179,15 +179,15 @@ namespace eCAL topic_quality_info.quality = topic_quality_; const std::unique_lock lock(topic_info_map_.mtx); - topic_info_map_.map->remove_deprecated(); - (*topic_info_map_.map)[topic_info_key] = topic_quality_info; + topic_info_map_.map.remove_deprecated(); + topic_info_map_.map[topic_info_key] = topic_quality_info; } void CDescGate::RemTopicDescription(SQualityTopicIdMap& topic_info_map_, const std::string& topic_name_, const Util::TopicId& topic_id_) { const std::unique_lock lock(topic_info_map_.mtx); - topic_info_map_.map->remove_deprecated(); - topic_info_map_.map->erase(STopicIdKey{ topic_name_, topic_id_ }); + topic_info_map_.map.remove_deprecated(); + topic_info_map_.map.erase(STopicIdKey{ topic_name_, topic_id_ }); } void CDescGate::ApplyServiceDescription(SQualityServiceIdMap& service_method_info_map_, @@ -209,8 +209,8 @@ namespace eCAL service_quality_info.response_quality = response_type_quality_; const std::lock_guard lock(service_method_info_map_.mtx); - service_method_info_map_.map->remove_deprecated(); - (*service_method_info_map_.map)[service_method_info_key] = service_quality_info; + service_method_info_map_.map.remove_deprecated(); + service_method_info_map_.map[service_method_info_key] = service_quality_info; } void CDescGate::RemServiceDescription(SQualityServiceIdMap& service_method_info_map_, const std::string& service_name_, const Util::ServiceId& service_id_) @@ -218,9 +218,9 @@ namespace eCAL std::list service_method_infos_to_remove; const std::lock_guard lock(service_method_info_map_.mtx); - service_method_info_map_.map->remove_deprecated(); + service_method_info_map_.map.remove_deprecated(); - for (auto&& service_it : *service_method_info_map_.map) + for (auto&& service_it : service_method_info_map_.map) { const auto service_method_info = service_it.first; if ((service_method_info.service_name == service_name_) @@ -232,7 +232,7 @@ namespace eCAL for (const auto& service_method_info : service_method_infos_to_remove) { - (*service_method_info_map_.map).erase(service_method_info); + service_method_info_map_.map.erase(service_method_info); } } } diff --git a/ecal/core/src/ecal_descgate.h b/ecal/core/src/ecal_descgate.h index 8ca57344cf..c79559e945 100644 --- a/ecal/core/src/ecal_descgate.h +++ b/ecal/core/src/ecal_descgate.h @@ -78,8 +78,8 @@ namespace eCAL void ApplySample(const Registration::Sample& sample_, eTLayerType layer_); // get publisher/subscriber maps - QualityTopicIdMap GetPublisher(); - QualityTopicIdMap GetSubscriber(); + QualityTopicIdMap GetPublishers(); + QualityTopicIdMap GetSubscribers(); // get service/clients maps QualityServiceIdMap GetServices(); @@ -97,23 +97,17 @@ namespace eCAL using QualityTopicIdExpMap = eCAL::Util::CExpMap; struct SQualityTopicIdMap { - explicit SQualityTopicIdMap(const std::chrono::milliseconds& timeout_) : - map(std::make_unique(timeout_)) - { - }; - mutable std::mutex mtx; - std::unique_ptr map; + explicit SQualityTopicIdMap(const std::chrono::milliseconds& timeout_) : map(timeout_) {}; + mutable std::mutex mtx; + QualityTopicIdExpMap map; }; using QualityServiceIdExpMap = eCAL::Util::CExpMap; struct SQualityServiceIdMap { - explicit SQualityServiceIdMap(const std::chrono::milliseconds& timeout_) : - map(std::make_unique(timeout_)) - { - }; - mutable std::mutex mtx; - std::unique_ptr map; + explicit SQualityServiceIdMap(const std::chrono::milliseconds& timeout_) : map(timeout_) {}; + mutable std::mutex mtx; + QualityServiceIdExpMap map; }; SQualityTopicIdMap m_publisher_info_map; @@ -121,30 +115,30 @@ namespace eCAL SQualityServiceIdMap m_service_info_map; SQualityServiceIdMap m_client_info_map; - QualityTopicIdMap GetTopics(const SQualityTopicIdMap& topic_map_); - QualityServiceIdMap GetServices(const SQualityServiceIdMap& service_method_info_map_); - - void ApplyTopicDescription(SQualityTopicIdMap& topic_info_map_, - const std::string& topic_name_, - const Util::TopicId& topic_id_, - const SDataTypeInformation& topic_info_, - Util::DescQualityFlags topic_quality_); - - void RemTopicDescription(SQualityTopicIdMap& topic_info_map_, - const std::string& topic_name_, - const Util::TopicId& topic_id_); - - void ApplyServiceDescription(SQualityServiceIdMap& service_method_info_map_, - const std::string& service_name_, - const std::string& method_name_, - const Util::ServiceId& service_id_, - const SDataTypeInformation& request_type_information_, - const SDataTypeInformation& response_type_information_, - Util::DescQualityFlags request_type_quality_, - Util::DescQualityFlags response_type_quality_); - - void RemServiceDescription(SQualityServiceIdMap& service_method_info_map_, - const std::string& service_name_, - const Util::ServiceId& service_id_); + QualityTopicIdMap GetTopics(SQualityTopicIdMap& topic_map_); + QualityServiceIdMap GetServices(SQualityServiceIdMap& service_method_info_map_); + + static void ApplyTopicDescription(SQualityTopicIdMap& topic_info_map_, + const std::string& topic_name_, + const Util::TopicId& topic_id_, + const SDataTypeInformation& topic_info_, + Util::DescQualityFlags topic_quality_); + + static void RemTopicDescription(SQualityTopicIdMap& topic_info_map_, + const std::string& topic_name_, + const Util::TopicId& topic_id_); + + static void ApplyServiceDescription(SQualityServiceIdMap& service_method_info_map_, + const std::string& service_name_, + const std::string& method_name_, + const Util::ServiceId& service_id_, + const SDataTypeInformation& request_type_information_, + const SDataTypeInformation& response_type_information_, + Util::DescQualityFlags request_type_quality_, + Util::DescQualityFlags response_type_quality_); + + static void RemServiceDescription(SQualityServiceIdMap& service_method_info_map_, + const std::string& service_name_, + const Util::ServiceId& service_id_); }; } diff --git a/ecal/core/src/ecal_util.cpp b/ecal/core/src/ecal_util.cpp index 253e0fcec5..44728871e1 100644 --- a/ecal/core/src/ecal_util.cpp +++ b/ecal/core/src/ecal_util.cpp @@ -294,7 +294,7 @@ namespace eCAL if (g_descgate() == nullptr) return multi_map; // insert publisher into target multimap - for (const auto& topic : g_descgate()->GetPublisher()) + for (const auto& topic : g_descgate()->GetPublishers()) { multi_map.insert(std::pair(topic.first.topic_name, topic.second)); } @@ -313,7 +313,7 @@ namespace eCAL if (g_descgate() == nullptr) return multi_map; // insert subscriber into target multimap - for (const auto& topic : g_descgate()->GetSubscriber()) + for (const auto& topic : g_descgate()->GetSubscribers()) { multi_map.insert(std::pair(topic.first.topic_name, topic.second)); } @@ -399,8 +399,8 @@ namespace eCAL quality_topic_info_map_.clear(); if (g_descgate() == nullptr) return; - QualityTopicIdMap pub_sub_map = g_descgate()->GetPublisher(); - QualityTopicIdMap sub_map = g_descgate()->GetSubscriber(); + QualityTopicIdMap pub_sub_map = g_descgate()->GetPublishers(); + QualityTopicIdMap sub_map = g_descgate()->GetSubscribers(); pub_sub_map.insert(sub_map.begin(), sub_map.end()); // transform into a map with the highest quality data type information diff --git a/ecal/tests/cpp/descgate_test/src/getpublisher.cpp b/ecal/tests/cpp/descgate_test/src/getpublisher.cpp index 6e6104cead..6ab1157a48 100644 --- a/ecal/tests/cpp/descgate_test/src/getpublisher.cpp +++ b/ecal/tests/cpp/descgate_test/src/getpublisher.cpp @@ -90,14 +90,14 @@ TEST(core_cpp_descgate, PublisherExpiration) desc_gate.ApplySample(CreatePublisher("pub1", 1), eCAL::tl_none); std::this_thread::sleep_for(std::chrono::milliseconds(DESCGATE_EXPIRATION_MS / 2)); - EXPECT_EQ(1, desc_gate.GetPublisher().size()); + EXPECT_EQ(1, desc_gate.GetPublishers().size()); } // now let the sample expire std::this_thread::sleep_for(std::chrono::milliseconds(DESCGATE_EXPIRATION_MS)); // sample should be expired - EXPECT_EQ(0, desc_gate.GetPublisher().size()); + EXPECT_EQ(0, desc_gate.GetPublishers().size()); } TEST(core_cpp_descgate, PublisherQualities) @@ -111,7 +111,7 @@ TEST(core_cpp_descgate, PublisherQualities) desc_gate.ApplySample(CreatePublisher("pub2", 2), eCAL::tl_none); // check gate size - auto sample_map = desc_gate.GetPublisher(); + auto sample_map = desc_gate.GetPublishers(); EXPECT_EQ(2, sample_map.size()); // check pub1 quality @@ -144,7 +144,7 @@ TEST(core_cpp_descgate, PublisherQualities) std::this_thread::sleep_for(std::chrono::milliseconds(DESCGATE_EXPIRATION_MS)); // sample should be expired - EXPECT_EQ(0, desc_gate.GetPublisher().size()); + EXPECT_EQ(0, desc_gate.GetPublishers().size()); } TEST(core_cpp_descgate, ManyPublisher) @@ -159,13 +159,13 @@ TEST(core_cpp_descgate, ManyPublisher) } // map should contain num_pub samples - EXPECT_EQ(num_pub, desc_gate.GetPublisher().size()); + EXPECT_EQ(num_pub, desc_gate.GetPublishers().size()); // now let the samples expire std::this_thread::sleep_for(std::chrono::milliseconds(DESCGATE_EXPIRATION_MS)); // samples should be expired - EXPECT_EQ(0, desc_gate.GetPublisher().size()); + EXPECT_EQ(0, desc_gate.GetPublishers().size()); } TEST(core_cpp_descgate, SubscriberExpiration) @@ -179,14 +179,14 @@ TEST(core_cpp_descgate, SubscriberExpiration) desc_gate.ApplySample(CreateSubscriber("sub1", 1), eCAL::tl_none); std::this_thread::sleep_for(std::chrono::milliseconds(DESCGATE_EXPIRATION_MS / 2)); - EXPECT_EQ(1, desc_gate.GetSubscriber().size()); + EXPECT_EQ(1, desc_gate.GetSubscribers().size()); } // now let the sample expire std::this_thread::sleep_for(std::chrono::milliseconds(DESCGATE_EXPIRATION_MS)); // sample should be expired - EXPECT_EQ(0, desc_gate.GetSubscriber().size()); + EXPECT_EQ(0, desc_gate.GetSubscribers().size()); } TEST(core_cpp_descgate, SubscriberQualities) @@ -200,7 +200,7 @@ TEST(core_cpp_descgate, SubscriberQualities) desc_gate.ApplySample(CreateSubscriber("sub2", 2), eCAL::tl_none); // check gate size - auto sample_map = desc_gate.GetSubscriber(); + auto sample_map = desc_gate.GetSubscribers(); EXPECT_EQ(2, sample_map.size()); // check sub1 quality @@ -233,7 +233,7 @@ TEST(core_cpp_descgate, SubscriberQualities) std::this_thread::sleep_for(std::chrono::milliseconds(DESCGATE_EXPIRATION_MS)); // sample should be expired - EXPECT_EQ(0, desc_gate.GetSubscriber().size()); + EXPECT_EQ(0, desc_gate.GetSubscribers().size()); } TEST(core_cpp_descgate, ManySubscriber) @@ -248,13 +248,13 @@ TEST(core_cpp_descgate, ManySubscriber) } // map should contain num_sub samples - EXPECT_EQ(num_sub, desc_gate.GetSubscriber().size()); + EXPECT_EQ(num_sub, desc_gate.GetSubscribers().size()); // now let the samples expire std::this_thread::sleep_for(std::chrono::milliseconds(DESCGATE_EXPIRATION_MS)); // samples should be expired - EXPECT_EQ(0, desc_gate.GetSubscriber().size()); + EXPECT_EQ(0, desc_gate.GetSubscribers().size()); } TEST(core_cpp_descgate, ServiceExpiration) From 5fcdbe753aede9c41f8a3c1c7085043dcf9e3a88 Mon Sep 17 00:00:00 2001 From: rex-schilasky <49162693+rex-schilasky@users.noreply.github.com> Date: Mon, 22 Apr 2024 22:06:15 +0200 Subject: [PATCH 22/27] GetPublisher > GetPublishers .. vector > set --- ecal/core/include/ecal/ecal_util.h | 77 +++++--- ecal/core/src/ecal_descgate.h | 17 +- ecal/core/src/ecal_util.cpp | 166 +++++++++--------- .../src/monitoring_get_services.cpp | 6 +- .../src/monitoring_get_topics.cpp | 4 +- .../cpp/util_test/src/util_getclients.cpp | 15 +- .../cpp/util_test/src/util_getservices.cpp | 15 +- .../cpp/util_test/src/util_gettopics.cpp | 8 +- 8 files changed, 166 insertions(+), 142 deletions(-) diff --git a/ecal/core/include/ecal/ecal_util.h b/ecal/core/include/ecal/ecal_util.h index d57a660074..e09e52460b 100644 --- a/ecal/core/include/ecal/ecal_util.h +++ b/ecal/core/include/ecal/ecal_util.h @@ -32,7 +32,6 @@ #include #include #include -#include namespace eCAL { @@ -62,7 +61,13 @@ namespace eCAL TopicId id = 0; SDataTypeInformation info; DescQualityFlags quality = DescQualityFlags::NO_QUALITY; + + bool operator<(const SQualityTopicInfo& other) const + { + return id <= other.id; + } }; + using QualityTopicInfoMultiMap = std::multimap; using ServiceId = std::uint64_t; struct SQualityServiceInfo @@ -71,7 +76,25 @@ namespace eCAL SServiceMethodInformation info; DescQualityFlags request_quality = DescQualityFlags::NO_QUALITY; DescQualityFlags response_quality = DescQualityFlags::NO_QUALITY; + + bool operator<(const SQualityServiceInfo& other) const + { + return id <= other.id; + } + }; + struct SServiceMethod + { + std::string service_name; + std::string method_name; + + bool operator<(const SServiceMethod& other) const + { + if (service_name != other.service_name) + return service_name < other.service_name; + return method_name < other.method_name; + } }; + using QualityServiceInfoMultimap = std::multimap; /** * @brief Retrieve eCAL configuration path. @@ -162,64 +185,64 @@ namespace eCAL * * @return MultiMap containing the quality datatype information and the topic id's. **/ - ECAL_API std::multimap GetPublisher(); + ECAL_API QualityTopicInfoMultiMap GetPublishers(); /** - * @brief Get data type information with quality and topic id for this publisher. + * @brief Get data type information with quality and topic id for this publishers. * * @param topic_name_ Topic name. * - * @return Vector containing the quality datatype information for this publisher. + * @return Set containing the quality datatype information for this publisher. **/ - ECAL_API std::vector GetPublisher(const std::string& topic_name_); + ECAL_API std::set GetPublishers(const std::string& topic_name_); /** - * @brief Get complete snapshot of data type information with quality and topic id for all known subscriber. + * @brief Get complete snapshot of data type information with quality and topic id for all known subscribers. * * @return MultiMap containing the quality datatype information and the topic id's. **/ - ECAL_API std::multimap GetSubscriber(); + ECAL_API QualityTopicInfoMultiMap GetSubscribers(); /** * @brief Get data type information with quality and topic id for this subscriber. * * @param topic_name_ Topic name. * - * @return Vector containing the quality datatype information for this subscriber. + * @return Set containing the quality datatype information for this subscriber. **/ - ECAL_API std::vector GetSubscriber(const std::string& topic_name_); + ECAL_API std::set GetSubscribers(const std::string& topic_name_); /** - * @brief Get highest quality data type information out of a vector of quality data type information. + * @brief Get highest quality data type information out of a set of quality data type information. * - * @param quality_topic_info_vec_ Vector of quality data type information + * @param quality_topic_info_set_ Set of quality data type information * * @return Highest quality data type information. **/ - ECAL_API SDataTypeInformation GetHighestQualityDataTypeInformation(const std::vector& quality_topic_info_vec_); + ECAL_API SDataTypeInformation GetHighestQualityDataTypeInformation(const std::set& quality_topic_info_set_); /** * @brief Get complete snapshot of service method information with quality and service id for all known services. * * @return MultiMap containing the quality datatype information and the service id's. **/ - ECAL_API std::multimap, SQualityServiceInfo> GetServices(); + ECAL_API QualityServiceInfoMultimap GetServices(); /** * @brief Get complete snapshot of service method information with quality and client id for all known clients. * * @return MultiMap containing the quality datatype information and the client id's. **/ - ECAL_API std::multimap, SQualityServiceInfo> GetClients(); + ECAL_API QualityServiceInfoMultimap GetClients(); /** - * @brief Get highest quality service method type information out of a vector of quality service method information. + * @brief Get highest quality service method type information out of a set of quality service method information. * - * @param quality_service_info_vec_ Vector of quality service method information + * @param quality_service_info_set_ Set of quality service method information * * @return Highest quality service method information. **/ - ECAL_API SServiceMethodInformation GetHighestQualityServiceMethodInformation(const std::vector& quality_service_info_vec_); + ECAL_API SServiceMethodInformation GetHighestQualityServiceMethodInformation(const std::set& quality_service_info_set_); /** * @brief Get complete topic map. @@ -240,9 +263,9 @@ namespace eCAL /** * @brief Get all topic names. * - * @param topic_names_ Vector to store the topic names. + * @param topic_names_ Set to store the topic names. **/ - ECAL_API void GetTopicNames(std::vector& topic_names_); + ECAL_API void GetTopicNames(std::set& topic_names_); /** * @brief Gets description of the specified topic. @@ -260,7 +283,7 @@ namespace eCAL * @param service_method_info_map_ Map to store the service/method descriptions. * Map { (ServiceName, MethodName) -> SServiceMethodInformation } mapping of all currently known services. **/ - ECAL_API void GetServices(std::map, SServiceMethodInformation>& service_method_info_map_); + ECAL_API void GetServices(std::map& service_method_info_map_); /** * @brief Get complete quality service map. @@ -268,14 +291,14 @@ namespace eCAL * @param quality_service_info_map_ Map to store the quality service/method descriptions. * Map { (ServiceName, MethodName) -> SQualityServiceMethodInformation } mapping of all currently known services. **/ - ECAL_API void GetServices(std::map, SQualityServiceInfo>& quality_service_info_map_); + ECAL_API void GetServices(std::map& quality_service_info_map_); /** * @brief Get all service/method names. * - * @param service_method_names_ Vector to store the service/method tuples (Vector { (ServiceName, MethodName) }). + * @param service_method_names_ Set to store the service/method names (Set { (ServiceName, MethodName) }). **/ - ECAL_API void GetServiceMethodNames(std::vector>& service_method_names_); + ECAL_API void GetServiceMethodNames(std::set& service_method_names_); /** * @brief Gets service method request and response type names. @@ -307,7 +330,7 @@ namespace eCAL * @param client_method_info_map_ Map to store the client/method descriptions. * Map { (ClientName, MethodName) -> SServiceMethodInformation } mapping of all currently known clients. **/ - ECAL_API void GetClients(std::map, SServiceMethodInformation>& client_method_info_map_); + ECAL_API void GetClients(std::map& client_method_info_map_); /** * @brief Get complete quality client map. @@ -315,14 +338,14 @@ namespace eCAL * @param quality_client_info_map_ Map to store the quality client/method descriptions. * Map { (ClientName, MethodName) -> SQualityServiceMethodInformation } mapping of all currently known clients. **/ - ECAL_API void GetClients(std::map, SQualityServiceInfo>& quality_client_info_map_); + ECAL_API void GetClients(std::map& quality_client_info_map_); /** * @brief Get all client/method names. * - * @param client_method_names_ Vector to store the client/method tuples (Vector { (ClientName, MethodName) }). + * @param client_method_names_ Set to store the client/method names (Set { (ClientName, MethodName) }). **/ - ECAL_API void GetClientMethodNames(std::vector>& client_method_names_); + ECAL_API void GetClientMethodNames(std::set& client_method_names_); /** * @brief Gets client method request and response type names. diff --git a/ecal/core/src/ecal_descgate.h b/ecal/core/src/ecal_descgate.h index c79559e945..b4e622f7eb 100644 --- a/ecal/core/src/ecal_descgate.h +++ b/ecal/core/src/ecal_descgate.h @@ -110,13 +110,8 @@ namespace eCAL QualityServiceIdExpMap map; }; - SQualityTopicIdMap m_publisher_info_map; - SQualityTopicIdMap m_subscriber_info_map; - SQualityServiceIdMap m_service_info_map; - SQualityServiceIdMap m_client_info_map; - - QualityTopicIdMap GetTopics(SQualityTopicIdMap& topic_map_); - QualityServiceIdMap GetServices(SQualityServiceIdMap& service_method_info_map_); + static QualityTopicIdMap GetTopics(SQualityTopicIdMap& topic_map_); + static QualityServiceIdMap GetServices(SQualityServiceIdMap& service_method_info_map_); static void ApplyTopicDescription(SQualityTopicIdMap& topic_info_map_, const std::string& topic_name_, @@ -140,5 +135,13 @@ namespace eCAL static void RemServiceDescription(SQualityServiceIdMap& service_method_info_map_, const std::string& service_name_, const Util::ServiceId& service_id_); + + // internal quality topic info publisher/subscriber maps + SQualityTopicIdMap m_publisher_info_map; + SQualityTopicIdMap m_subscriber_info_map; + + // internal quality service info service/client maps + SQualityServiceIdMap m_service_info_map; + SQualityServiceIdMap m_client_info_map; }; } diff --git a/ecal/core/src/ecal_util.cpp b/ecal/core/src/ecal_util.cpp index 44728871e1..e398b1e13e 100644 --- a/ecal/core/src/ecal_util.cpp +++ b/ecal/core/src/ecal_util.cpp @@ -23,6 +23,7 @@ #include "pubsub/ecal_pubgate.h" #include +#include #include #include #include @@ -30,46 +31,49 @@ namespace { /** - * @brief Extract a vector of all SQualityTopicInfo matching the given topic name. + * @brief Extract a set of all SQualityTopicInfo matching the given topic name. * * @param topic_name_ The topic name. * @param quality_data_type_info_multi_map_ MultiMap { TopicName -> SQualityTopicInfo }. * - * @return Vector of SQualityTopicInfo + * @return Set of SQualityTopicInfo **/ - std::vector GetQualityTopicInfoVec(const std::string& topic_name_, const std::multimap& quality_data_type_info_multi_map_) + std::set GetQualityTopicInfoSet(const std::string& topic_name_, const std::multimap& quality_data_type_info_multi_map_) { - std::vector quality_topic_info_vec; + std::set quality_topic_info_set; const auto topic_info_range = quality_data_type_info_multi_map_.equal_range(topic_name_); for (auto topic_info_range_it = topic_info_range.first; topic_info_range_it != topic_info_range.second; ++topic_info_range_it) { - quality_topic_info_vec.push_back(topic_info_range_it->second); + quality_topic_info_set.insert(topic_info_range_it->second); } - return quality_topic_info_vec; + return quality_topic_info_set; } /** - * @brief Extract a vector of all SQualityServiceInfo matching the given service name/method name. + * @brief Extract a set of all SQualityServiceInfo matching the given service name/method name. * * @param service_name_ The service name. * @param method_name_ The method name. * @param quality_service_info_multi_map_ MultiMap { -> SQualityServiceInfo }. * - * @return Vector of SQualityServiceInfo + * @return Set of SQualityServiceInfo **/ - std::vector GetQualityServiceInfoVec(const std::string& service_name_, const std::string& method_name_, std::multimap, eCAL::Util::SQualityServiceInfo> quality_service_info_multi_map_) + std::set GetQualityServiceInfoSet(const std::string& service_name_, const std::string& method_name_, std::multimap quality_service_info_multi_map_) { - std::vector quality_service_info_vec; + std::set quality_service_info_set; - const auto service_info_range = quality_service_info_multi_map_.equal_range(std::make_pair(service_name_, method_name_)); + eCAL::Util::SServiceMethod key; + key.service_name = service_name_; + key.method_name = method_name_; + const auto service_info_range = quality_service_info_multi_map_.equal_range(key); for (auto service_info_range_it = service_info_range.first; service_info_range_it != service_info_range.second; ++service_info_range_it) { - quality_service_info_vec.push_back(service_info_range_it->second); + quality_service_info_set.insert(service_info_range_it->second); } - return quality_service_info_vec; + return quality_service_info_set; } /** @@ -117,16 +121,19 @@ namespace * * @return std::map, SQualityServiceInfo> **/ - std::map, eCAL::Util::SQualityServiceInfo> ReduceQualityServiceIdMap(const eCAL::QualityServiceIdMap& source_map_) + std::map ReduceQualityServiceIdMap(const eCAL::QualityServiceIdMap& source_map_) { - std::map, eCAL::Util::SQualityServiceInfo> target_map; + std::map target_map; for (const auto& source_pair : source_map_) { const auto& source_key = source_pair.first; const auto& source_value = source_pair.second; - auto target_it = target_map.find(std::make_tuple(source_key.service_name, source_key.method_name)); + eCAL::Util::SServiceMethod key; + key.service_name = source_key.service_name; + key.method_name = source_key.method_name; + auto target_it = target_map.find(key); if (target_it != target_map.end()) { // key exists in target map @@ -140,7 +147,10 @@ namespace else { // key does not exist in target map, insert source pair - target_map.insert(std::make_pair(std::make_tuple(source_key.service_name, source_key.method_name), source_pair.second)); + eCAL::Util::SServiceMethod key; + key.service_name = source_key.service_name; + key.method_name = source_key.method_name; + target_map.insert(std::make_pair(key, source_pair.second)); } } @@ -288,9 +298,9 @@ namespace eCAL } #endif // ECAL_CORE_MONITORING - std::multimap GetPublisher() + QualityTopicInfoMultiMap GetPublishers() { - std::multimap multi_map; + QualityTopicInfoMultiMap multi_map; if (g_descgate() == nullptr) return multi_map; // insert publisher into target multimap @@ -302,14 +312,14 @@ namespace eCAL return multi_map; } - std::vector GetPublisher(const std::string& topic_name_) + std::set GetPublishers(const std::string& topic_name_) { - return ::GetQualityTopicInfoVec(topic_name_, GetPublisher()); + return ::GetQualityTopicInfoSet(topic_name_, GetPublishers()); } - std::multimap GetSubscriber() + QualityTopicInfoMultiMap GetSubscribers() { - std::multimap multi_map; + QualityTopicInfoMultiMap multi_map; if (g_descgate() == nullptr) return multi_map; // insert subscriber into target multimap @@ -321,15 +331,15 @@ namespace eCAL return multi_map; } - std::vector GetSubscriber(const std::string& topic_name_) + std::set GetSubscribers(const std::string& topic_name_) { - return ::GetQualityTopicInfoVec(topic_name_, GetSubscriber()); + return ::GetQualityTopicInfoSet(topic_name_, GetSubscribers()); } - SDataTypeInformation GetHighestQualityDataTypeInformation(const std::vector& quality_topic_info_vec_) + SDataTypeInformation GetHighestQualityDataTypeInformation(const std::set& quality_topic_info_set_) { SQualityTopicInfo highest_quality_topic_info; - for (const auto& info : quality_topic_info_vec_) + for (const auto& info : quality_topic_info_set_) { if (info.quality > highest_quality_topic_info.quality) { @@ -339,37 +349,43 @@ namespace eCAL return highest_quality_topic_info.info; } - std::multimap, SQualityServiceInfo> GetServices() + QualityServiceInfoMultimap GetServices() { - std::multimap, SQualityServiceInfo> multi_map; + QualityServiceInfoMultimap multi_map; if (g_descgate() == nullptr) return multi_map; // insert services into target multimap for (const auto& service : g_descgate()->GetServices()) { - multi_map.insert(std::pair, SQualityServiceInfo>(std::make_tuple(service.first.service_name, service.first.method_name), service.second)); + SServiceMethod key; + key.service_name = service.first.service_name; + key.method_name = service.first.method_name; + multi_map.insert(std::pair(key, service.second)); } return multi_map; } - std::multimap, SQualityServiceInfo> GetClients() + QualityServiceInfoMultimap GetClients() { - std::multimap, SQualityServiceInfo> multi_map; + QualityServiceInfoMultimap multi_map; if (g_descgate() == nullptr) return multi_map; // insert clients into target multimap for (const auto& client : g_descgate()->GetClients()) { - multi_map.insert(std::pair, SQualityServiceInfo>(std::make_tuple(client.first.service_name, client.first.method_name), client.second)); + SServiceMethod key; + key.service_name = client.first.service_name; + key.method_name = client.first.method_name; + multi_map.insert(std::pair(key, client.second)); } return multi_map; } - SServiceMethodInformation GetHighestQualityServiceMethodInformation(const std::vector& quality_service_info_vec_) + SServiceMethodInformation GetHighestQualityServiceMethodInformation(const std::set& quality_service_info_set_) { SQualityServiceInfo highest_quality_service_info; - for (const auto& info : quality_service_info_vec_) + for (const auto& info : quality_service_info_set_) { if ( (info.request_quality > highest_quality_service_info.request_quality) || (info.response_quality > highest_quality_service_info.response_quality)) @@ -407,55 +423,51 @@ namespace eCAL quality_topic_info_map_ = ReduceQualityTopicIdMap(pub_sub_map); } - void GetTopicNames(std::vector& topic_names_) + void GetTopicNames(std::set& topic_names_) { topic_names_.clear(); // get publisher & subscriber multi maps - auto pub_multi_map = GetPublisher(); - auto sub_multi_map = GetSubscriber(); + auto pub_multi_map = GetPublishers(); + auto sub_multi_map = GetSubscribers(); // filter out unique topic names into a set - std::set set; for (const auto& publisher : pub_multi_map) { - set.insert(publisher.first); + topic_names_.insert(publisher.first); } for (const auto& subscriber : sub_multi_map) { - set.insert(subscriber.first); + topic_names_.insert(subscriber.first); } - - // transform set into target vector - topic_names_ = std::vector(set.begin(), set.end()); } bool GetTopicDataTypeInformation(const std::string& topic_name_, SDataTypeInformation& data_type_info_) { - auto info_vec = GetPublisher(topic_name_); - const auto sub_info_vec = GetSubscriber(topic_name_); + auto info_set = GetPublishers(topic_name_); + const auto sub_info_set = GetSubscribers(topic_name_); - info_vec.insert(info_vec.end(), sub_info_vec.begin(), sub_info_vec.end()); - data_type_info_ = GetHighestQualityDataTypeInformation(info_vec); + info_set.insert(sub_info_set.begin(), sub_info_set.end()); + data_type_info_ = GetHighestQualityDataTypeInformation(info_set); - return !info_vec.empty(); + return !info_set.empty(); } - void GetServices(std::map, SServiceMethodInformation>& service_method_info_map_) + void GetServices(std::map& service_method_info_map_) { service_method_info_map_.clear(); - std::map, SQualityServiceInfo> quality_service_method_info_map; + std::map quality_service_method_info_map; GetServices(quality_service_method_info_map); // transform into target map for (const auto& quality_service_method_info : quality_service_method_info_map) { - service_method_info_map_.insert(std::pair, SServiceMethodInformation>(quality_service_method_info.first, quality_service_method_info.second.info)); + service_method_info_map_.insert(std::pair(quality_service_method_info.first, quality_service_method_info.second.info)); } } - void GetServices(std::map, SQualityServiceInfo>& quality_service_info_map_) + void GetServices(std::map& quality_service_info_map_) { quality_service_info_map_.clear(); if (g_descgate() == nullptr) return; @@ -464,7 +476,7 @@ namespace eCAL quality_service_info_map_ = ReduceQualityServiceIdMap(g_descgate()->GetServices()); } - void GetServiceMethodNames(std::vector>& service_method_names_) + void GetServiceMethodNames(std::set& service_method_names_) { service_method_names_.clear(); @@ -472,53 +484,49 @@ namespace eCAL auto multi_map = GetServices(); // filter out unique service names into a set - std::set> set; for (const auto& service : multi_map) { - set.insert(service.first); + service_method_names_.insert(service.first); } - - // transform set into target vector - service_method_names_ = std::vector>(set.begin(), set.end()); } bool GetServiceTypeNames(const std::string& service_name_, const std::string& method_name_, std::string& req_type_, std::string& resp_type_) { - const std::vector service_method_info_vec = GetQualityServiceInfoVec(service_name_, method_name_, GetServices()); + const auto service_method_info_set = GetQualityServiceInfoSet(service_name_, method_name_, GetServices()); - const SServiceMethodInformation service_method_info = GetHighestQualityServiceMethodInformation(service_method_info_vec); + const SServiceMethodInformation service_method_info = GetHighestQualityServiceMethodInformation(service_method_info_set); req_type_ = service_method_info.request_type.name; resp_type_ = service_method_info.response_type.name; - return !service_method_info_vec.empty(); + return !service_method_info_set.empty(); } bool GetServiceDescription(const std::string& service_name_, const std::string& method_name_, std::string& req_desc_, std::string& resp_desc_) { - const std::vector service_method_info_vec = GetQualityServiceInfoVec(service_name_, method_name_, GetServices()); + const auto service_method_info_set = GetQualityServiceInfoSet(service_name_, method_name_, GetServices()); - const SServiceMethodInformation service_method_info = GetHighestQualityServiceMethodInformation(service_method_info_vec); + const SServiceMethodInformation service_method_info = GetHighestQualityServiceMethodInformation(service_method_info_set); req_desc_ = service_method_info.request_type.descriptor; resp_desc_ = service_method_info.response_type.descriptor; - return !service_method_info_vec.empty(); + return !service_method_info_set.empty(); } - void GetClients(std::map, SServiceMethodInformation>& client_method_info_map_) + void GetClients(std::map& client_method_info_map_) { client_method_info_map_.clear(); - std::map, SQualityServiceInfo> quality_client_method_info_map_; + std::map quality_client_method_info_map_; GetClients(quality_client_method_info_map_); // transform into target map for (const auto& quality_client_method_info : quality_client_method_info_map_) { - client_method_info_map_.insert(std::pair, SServiceMethodInformation>(quality_client_method_info.first, quality_client_method_info.second.info)); + client_method_info_map_.insert(std::pair(quality_client_method_info.first, quality_client_method_info.second.info)); } } - void GetClients(std::map, SQualityServiceInfo>& quality_client_info_map_) + void GetClients(std::map& quality_client_info_map_) { quality_client_info_map_.clear(); if (g_descgate() == nullptr) return; @@ -527,7 +535,7 @@ namespace eCAL quality_client_info_map_ = ReduceQualityServiceIdMap(g_descgate()->GetClients()); } - void GetClientMethodNames(std::vector>& client_method_names_) + void GetClientMethodNames(std::set& client_method_names_) { client_method_names_.clear(); @@ -535,36 +543,32 @@ namespace eCAL auto multi_map = GetClients(); // filter out unique service names into a set - std::set> set; for (const auto& service : multi_map) { - set.insert(service.first); + client_method_names_.insert(service.first); } - - // transform set into target vector - client_method_names_ = std::vector>(set.begin(), set.end()); } bool GetClientTypeNames(const std::string& client_name_, const std::string& method_name_, std::string& req_type_, std::string& resp_type_) { - const std::vector service_method_info_vec = GetQualityServiceInfoVec(client_name_, method_name_, GetClients()); + const auto service_method_info_set = GetQualityServiceInfoSet(client_name_, method_name_, GetClients()); - const SServiceMethodInformation service_method_info = GetHighestQualityServiceMethodInformation(service_method_info_vec); + const SServiceMethodInformation service_method_info = GetHighestQualityServiceMethodInformation(service_method_info_set); req_type_ = service_method_info.request_type.name; resp_type_ = service_method_info.response_type.name; - return !service_method_info_vec.empty(); + return !service_method_info_set.empty(); } bool GetClientDescription(const std::string& client_name_, const std::string& method_name_, std::string& req_desc_, std::string& resp_desc_) { - const std::vector service_method_info_vec = GetQualityServiceInfoVec(client_name_, method_name_, GetClients()); + const auto service_method_info_set = GetQualityServiceInfoSet(client_name_, method_name_, GetClients()); - const SServiceMethodInformation service_method_info = GetHighestQualityServiceMethodInformation(service_method_info_vec); + const SServiceMethodInformation service_method_info = GetHighestQualityServiceMethodInformation(service_method_info_set); req_desc_ = service_method_info.request_type.descriptor; resp_desc_ = service_method_info.response_type.descriptor; - return !service_method_info_vec.empty(); + return !service_method_info_set.empty(); } std::pair SplitCombinedTopicType(const std::string& combined_topic_type_) diff --git a/ecal/samples/cpp/monitoring/monitoring_get_services/src/monitoring_get_services.cpp b/ecal/samples/cpp/monitoring/monitoring_get_services/src/monitoring_get_services.cpp index bdffe6bc46..fa72608997 100644 --- a/ecal/samples/cpp/monitoring/monitoring_get_services/src/monitoring_get_services.cpp +++ b/ecal/samples/cpp/monitoring/monitoring_get_services/src/monitoring_get_services.cpp @@ -23,7 +23,7 @@ #include #include #include -#include +#include int main(int argc, char **argv) { @@ -38,7 +38,7 @@ int main(int argc, char **argv) { // GetServices { - std::map, eCAL::SServiceMethodInformation> service_info_map; + std::map service_info_map; start_time = std::chrono::steady_clock::now(); for (run = 0; run < runs; ++run) @@ -54,7 +54,7 @@ int main(int argc, char **argv) // GetServiceMethodNames { - std::vector> service_method_names; + std::set service_method_names; start_time = std::chrono::steady_clock::now(); for (run = 0; run < runs; ++run) diff --git a/ecal/samples/cpp/monitoring/monitoring_get_topics/src/monitoring_get_topics.cpp b/ecal/samples/cpp/monitoring/monitoring_get_topics/src/monitoring_get_topics.cpp index 692562dd15..7922c7b33b 100644 --- a/ecal/samples/cpp/monitoring/monitoring_get_topics/src/monitoring_get_topics.cpp +++ b/ecal/samples/cpp/monitoring/monitoring_get_topics/src/monitoring_get_topics.cpp @@ -22,7 +22,7 @@ #include #include #include -#include +#include int main(int argc, char **argv) { @@ -53,7 +53,7 @@ int main(int argc, char **argv) // GetTopicNames { - std::vector topic_names; + std::set topic_names; start_time = std::chrono::steady_clock::now(); for (run = 0; run < runs; ++run) diff --git a/ecal/tests/cpp/util_test/src/util_getclients.cpp b/ecal/tests/cpp/util_test/src/util_getclients.cpp index dbb0f872a3..28eac2422b 100644 --- a/ecal/tests/cpp/util_test/src/util_getclients.cpp +++ b/ecal/tests/cpp/util_test/src/util_getclients.cpp @@ -18,7 +18,6 @@ */ #include -#include #include @@ -32,7 +31,7 @@ TEST(core_cpp_util, ClientExpiration) // initialize eCAL API eCAL::Initialize(0, nullptr, "core_cpp_util"); - std::map, eCAL::SServiceMethodInformation> client_info_map; + std::map client_info_map; // create simple client and let it expire { @@ -51,13 +50,13 @@ TEST(core_cpp_util, ClientExpiration) EXPECT_EQ(client_info_map.size(), 1); // check client/method names - std::vector> client_method_names; + std::set client_method_names; eCAL::Util::GetClientMethodNames(client_method_names); EXPECT_EQ(client_method_names.size(), 1); - for (const auto& method_name : client_method_names) + for (const auto& name : client_method_names) { - EXPECT_EQ(std::get<0>(method_name), "foo::service"); - EXPECT_EQ(std::get<1>(method_name), "foo::method"); + EXPECT_EQ(name.service_name, "foo::service"); + EXPECT_EQ(name.method_name, "foo::method"); } // let's wait a monitoring timeout long @@ -89,7 +88,7 @@ TEST(core_cpp_util, ClientEqualQualities) // initialize eCAL API eCAL::Initialize(0, nullptr, "core_cpp_util"); - std::map, eCAL::SServiceMethodInformation> client_info_map; + std::map client_info_map; // create 2 clients with the same quality of data type information { @@ -178,7 +177,7 @@ TEST(core_cpp_util, ClientDifferentQualities) // initialize eCAL API eCAL::Initialize(0, nullptr, "core_cpp_util"); - std::map, eCAL::SServiceMethodInformation> client_info_map; + std::map client_info_map; // create 2 clients with different qualities of data type information { diff --git a/ecal/tests/cpp/util_test/src/util_getservices.cpp b/ecal/tests/cpp/util_test/src/util_getservices.cpp index 5d497dd195..fbf2239d43 100644 --- a/ecal/tests/cpp/util_test/src/util_getservices.cpp +++ b/ecal/tests/cpp/util_test/src/util_getservices.cpp @@ -18,7 +18,6 @@ */ #include -#include #include @@ -32,7 +31,7 @@ TEST(core_cpp_util, ServiceExpiration) // initialize eCAL API eCAL::Initialize(0, nullptr, "core_cpp_util"); - std::map, eCAL::SServiceMethodInformation> service_info_map; + std::map service_info_map; // create simple service and let it expire { @@ -47,13 +46,13 @@ TEST(core_cpp_util, ServiceExpiration) EXPECT_EQ(service_info_map.size(), 1); // check service/method names - std::vector> service_method_names; + std::set service_method_names; eCAL::Util::GetServiceMethodNames(service_method_names); EXPECT_EQ(service_method_names.size(), 1); - for (const auto& method_name : service_method_names) + for (const auto& name : service_method_names) { - EXPECT_EQ(std::get<0>(method_name), "foo::service"); - EXPECT_EQ(std::get<1>(method_name), "foo::method"); + EXPECT_EQ(name.service_name, "foo::service"); + EXPECT_EQ(name.method_name, "foo::method"); } // let's wait a monitoring timeout long @@ -85,7 +84,7 @@ TEST(core_cpp_util, ServiceEqualQualities) // initialize eCAL API eCAL::Initialize(0, nullptr, "core_cpp_util"); - std::map, eCAL::SServiceMethodInformation> service_info_map; + std::map service_info_map; // create 2 services with the same quality of data type information { @@ -166,7 +165,7 @@ TEST(core_cpp_util, ServiceDifferentQualities) // initialize eCAL API eCAL::Initialize(0, nullptr, "core_cpp_util"); - std::map, eCAL::SServiceMethodInformation> service_info_map; + std::map service_info_map; // create 2 services with different qualities of data type information { diff --git a/ecal/tests/cpp/util_test/src/util_gettopics.cpp b/ecal/tests/cpp/util_test/src/util_gettopics.cpp index 2dd162b864..a20a53e9b9 100644 --- a/ecal/tests/cpp/util_test/src/util_gettopics.cpp +++ b/ecal/tests/cpp/util_test/src/util_gettopics.cpp @@ -19,10 +19,6 @@ #include -#include -#include -#include - #include enum { @@ -148,7 +144,7 @@ TEST(core_cpp_util, GetTopicsParallel) auto get_topics_from_ecal = [&]() { size_t found_topics = 0; - std::vector tmp_topic_names; + std::set tmp_topic_names; std::map topics; do { eCAL::Util::GetTopicNames(tmp_topic_names); @@ -181,7 +177,7 @@ TEST(core_cpp_util, GetTopicsParallel) th.join(); } - std::vector final_topic_names; + std::set final_topic_names; std::map final_topics; eCAL::Util::GetTopicNames(final_topic_names); eCAL::Util::GetTopics(final_topics); From d6b0709f2831ad557890d0a56b6bbad8345b5fcf Mon Sep 17 00:00:00 2001 From: rex-schilasky <49162693+rex-schilasky@users.noreply.github.com> Date: Mon, 22 Apr 2024 22:39:57 +0200 Subject: [PATCH 23/27] includes added --- ecal/tests/cpp/util_test/src/util_gettopics.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ecal/tests/cpp/util_test/src/util_gettopics.cpp b/ecal/tests/cpp/util_test/src/util_gettopics.cpp index a20a53e9b9..2665df9924 100644 --- a/ecal/tests/cpp/util_test/src/util_gettopics.cpp +++ b/ecal/tests/cpp/util_test/src/util_gettopics.cpp @@ -21,6 +21,10 @@ #include +#include +#include +#include + enum { CMN_MONITORING_TIMEOUT_MS = (5000 + 100), CMN_REGISTRATION_REFRESH_MS = (1000 + 100) From f82d20d41c73c62a25b7dffb1b15089f0ac035c6 Mon Sep 17 00:00:00 2001 From: rex-schilasky <49162693+rex-schilasky@users.noreply.github.com> Date: Tue, 23 Apr 2024 20:54:50 +0200 Subject: [PATCH 24/27] a few keller-tidy --- ecal/core/include/ecal/ecal_util.h | 4 +--- ecal/core/src/ecal_descgate.h | 11 +++-------- ecal/core/src/ecal_util.cpp | 4 ++-- 3 files changed, 6 insertions(+), 13 deletions(-) diff --git a/ecal/core/include/ecal/ecal_util.h b/ecal/core/include/ecal/ecal_util.h index e09e52460b..6c50887ec4 100644 --- a/ecal/core/include/ecal/ecal_util.h +++ b/ecal/core/include/ecal/ecal_util.h @@ -89,9 +89,7 @@ namespace eCAL bool operator<(const SServiceMethod& other) const { - if (service_name != other.service_name) - return service_name < other.service_name; - return method_name < other.method_name; + return std::tie(service_name, method_name) < std::tie(other.service_name, other.method_name); } }; using QualityServiceInfoMultimap = std::multimap; diff --git a/ecal/core/src/ecal_descgate.h b/ecal/core/src/ecal_descgate.h index b4e622f7eb..c633cb6174 100644 --- a/ecal/core/src/ecal_descgate.h +++ b/ecal/core/src/ecal_descgate.h @@ -33,6 +33,7 @@ #include #include #include +#include namespace eCAL { @@ -43,9 +44,7 @@ namespace eCAL bool operator<(const STopicIdKey& other) const { - if (topic_name != other.topic_name) - return topic_name < other.topic_name; - return topic_id < other.topic_id; + return std::tie(topic_name, topic_id) < std::tie(other.topic_name, other.topic_id); } }; @@ -57,11 +56,7 @@ namespace eCAL bool operator<(const SServiceIdKey& other) const { - if (service_name != other.service_name) - return service_name < other.service_name; - if (service_id != other.service_id) - return service_id < other.service_id; - return method_name < other.method_name; + return std::tie(service_name, service_id) < std::tie(other.service_name, other.service_id); } }; diff --git a/ecal/core/src/ecal_util.cpp b/ecal/core/src/ecal_util.cpp index e398b1e13e..6b905f1e67 100644 --- a/ecal/core/src/ecal_util.cpp +++ b/ecal/core/src/ecal_util.cpp @@ -38,7 +38,7 @@ namespace * * @return Set of SQualityTopicInfo **/ - std::set GetQualityTopicInfoSet(const std::string& topic_name_, const std::multimap& quality_data_type_info_multi_map_) + std::set GetQualityTopicInfoSet(const std::string& topic_name_, const eCAL::Util::QualityTopicInfoMultiMap& quality_data_type_info_multi_map_) { std::set quality_topic_info_set; @@ -60,7 +60,7 @@ namespace * * @return Set of SQualityServiceInfo **/ - std::set GetQualityServiceInfoSet(const std::string& service_name_, const std::string& method_name_, std::multimap quality_service_info_multi_map_) + std::set GetQualityServiceInfoSet(const std::string& service_name_, const std::string& method_name_, const eCAL::Util::QualityServiceInfoMultimap& quality_service_info_multi_map_) { std::set quality_service_info_set; From afa72a2051f3480476907be36e73c3fe72b21a87 Mon Sep 17 00:00:00 2001 From: rex-schilasky <49162693+rex-schilasky@users.noreply.github.com> Date: Wed, 24 Apr 2024 10:37:31 +0200 Subject: [PATCH 25/27] a few more keller-tidy --- ecal/core/include/ecal/ecal_util.h | 4 +- ecal/core/src/ecal_descgate.cpp | 34 ++++---- ecal/core/src/ecal_descgate.h | 12 +-- ecal/core/src/ecal_util.cpp | 80 +++++-------------- .../cpp/descgate_test/src/getpublisher.cpp | 8 +- 5 files changed, 51 insertions(+), 87 deletions(-) diff --git a/ecal/core/include/ecal/ecal_util.h b/ecal/core/include/ecal/ecal_util.h index 6c50887ec4..34976c9a56 100644 --- a/ecal/core/include/ecal/ecal_util.h +++ b/ecal/core/include/ecal/ecal_util.h @@ -64,7 +64,7 @@ namespace eCAL bool operator<(const SQualityTopicInfo& other) const { - return id <= other.id; + return std::tie(quality, id) < std::tie(other.quality, other.id); } }; using QualityTopicInfoMultiMap = std::multimap; @@ -79,7 +79,7 @@ namespace eCAL bool operator<(const SQualityServiceInfo& other) const { - return id <= other.id; + return std::tie(request_quality, response_quality, id) < std::tie(other.request_quality, other.response_quality, other.id); } }; struct SServiceMethod diff --git a/ecal/core/src/ecal_descgate.cpp b/ecal/core/src/ecal_descgate.cpp index 31e76d9a92..ea80fd0d45 100644 --- a/ecal/core/src/ecal_descgate.cpp +++ b/ecal/core/src/ecal_descgate.cpp @@ -52,52 +52,56 @@ namespace eCAL } CDescGate::~CDescGate() = default; - QualityTopicIdMap CDescGate::GetPublishers() + Util::QualityTopicInfoMultiMap CDescGate::GetPublishers() { return GetTopics(m_publisher_info_map); } - QualityTopicIdMap CDescGate::GetSubscribers() + Util::QualityTopicInfoMultiMap CDescGate::GetSubscribers() { return GetTopics(m_subscriber_info_map); } - QualityServiceIdMap CDescGate::GetServices() + Util::QualityServiceInfoMultimap CDescGate::GetServices() { return GetServices(m_service_info_map); } - QualityServiceIdMap CDescGate::GetClients() + Util::QualityServiceInfoMultimap CDescGate::GetClients() { return GetServices(m_client_info_map); } - QualityTopicIdMap CDescGate::GetTopics(SQualityTopicIdMap& topic_map_) + Util::QualityTopicInfoMultiMap CDescGate::GetTopics(SQualityTopicIdMap& topic_info_map_) { - QualityTopicIdMap map; + Util::QualityTopicInfoMultiMap multi_map; - const std::lock_guard lock(topic_map_.mtx); - topic_map_.map.remove_deprecated(); + const std::lock_guard lock(topic_info_map_.mtx); + topic_info_map_.map.remove_deprecated(); - for (const auto& topic_map_it : topic_map_.map) + for (const auto& topic_map_it : topic_info_map_.map) { - map.emplace(topic_map_it.first, topic_map_it.second); + multi_map.insert(std::pair(topic_map_it.first.topic_name, topic_map_it.second)); } - return map; + + return multi_map; } - QualityServiceIdMap CDescGate::GetServices(SQualityServiceIdMap& service_method_info_map_) + Util::QualityServiceInfoMultimap CDescGate::GetServices(SQualityServiceIdMap& service_method_info_map_) { - QualityServiceIdMap map; + Util::QualityServiceInfoMultimap multi_map; const std::lock_guard lock(service_method_info_map_.mtx); service_method_info_map_.map.remove_deprecated(); for (const auto& service_method_info_map_it : service_method_info_map_.map) { - map.emplace(service_method_info_map_it.first, service_method_info_map_it.second); + Util::SServiceMethod key; + key.service_name = service_method_info_map_it.first.service_name; + key.method_name = service_method_info_map_it.first.method_name; + multi_map.insert(std::pair(key, service_method_info_map_it.second)); } - return map; + return multi_map; } void CDescGate::ApplySample(const Registration::Sample& sample_, eTLayerType /*layer_*/) diff --git a/ecal/core/src/ecal_descgate.h b/ecal/core/src/ecal_descgate.h index c633cb6174..7052797288 100644 --- a/ecal/core/src/ecal_descgate.h +++ b/ecal/core/src/ecal_descgate.h @@ -73,12 +73,12 @@ namespace eCAL void ApplySample(const Registration::Sample& sample_, eTLayerType layer_); // get publisher/subscriber maps - QualityTopicIdMap GetPublishers(); - QualityTopicIdMap GetSubscribers(); + Util::QualityTopicInfoMultiMap GetPublishers(); + Util::QualityTopicInfoMultiMap GetSubscribers(); // get service/clients maps - QualityServiceIdMap GetServices(); - QualityServiceIdMap GetClients(); + Util::QualityServiceInfoMultimap GetServices(); + Util::QualityServiceInfoMultimap GetClients(); // delete copy constructor and copy assignment operator CDescGate(const CDescGate&) = delete; @@ -105,8 +105,8 @@ namespace eCAL QualityServiceIdExpMap map; }; - static QualityTopicIdMap GetTopics(SQualityTopicIdMap& topic_map_); - static QualityServiceIdMap GetServices(SQualityServiceIdMap& service_method_info_map_); + static Util::QualityTopicInfoMultiMap GetTopics (SQualityTopicIdMap& topic_info_map_); + static Util::QualityServiceInfoMultimap GetServices(SQualityServiceIdMap& service_method_info_map_); static void ApplyTopicDescription(SQualityTopicIdMap& topic_info_map_, const std::string& topic_name_, diff --git a/ecal/core/src/ecal_util.cpp b/ecal/core/src/ecal_util.cpp index 6b905f1e67..c8f00afdc3 100644 --- a/ecal/core/src/ecal_util.cpp +++ b/ecal/core/src/ecal_util.cpp @@ -84,7 +84,7 @@ namespace * * @return std::map **/ - std::map ReduceQualityTopicIdMap(const eCAL::QualityTopicIdMap& source_map_) + std::map ReduceQualityTopicIdMap(const eCAL::Util::QualityTopicInfoMultiMap& source_map_) { std::map target_map; @@ -93,7 +93,7 @@ namespace const auto& source_key = source_pair.first; const auto& source_value = source_pair.second; - auto target_it = target_map.find(source_key.topic_name); + auto target_it = target_map.find(source_key); if (target_it != target_map.end()) { // key exists in target map @@ -106,7 +106,7 @@ namespace else { // key does not exist in target map, insert source pair - target_map.insert(std::make_pair(source_key.topic_name, source_value)); + target_map.insert(std::make_pair(source_key, source_value)); } } @@ -121,19 +121,19 @@ namespace * * @return std::map, SQualityServiceInfo> **/ - std::map ReduceQualityServiceIdMap(const eCAL::QualityServiceIdMap& source_map_) + std::map ReduceQualityServiceIdMap(const eCAL::Util::QualityServiceInfoMultimap& source_map_) { std::map target_map; for (const auto& source_pair : source_map_) { - const auto& source_key = source_pair.first; + const auto& source_key = source_pair.first; const auto& source_value = source_pair.second; - eCAL::Util::SServiceMethod key; - key.service_name = source_key.service_name; - key.method_name = source_key.method_name; - auto target_it = target_map.find(key); + eCAL::Util::SServiceMethod target_key; + target_key.service_name = source_key.service_name; + target_key.method_name = source_key.method_name; + auto target_it = target_map.find(target_key); if (target_it != target_map.end()) { // key exists in target map @@ -147,10 +147,7 @@ namespace else { // key does not exist in target map, insert source pair - eCAL::Util::SServiceMethod key; - key.service_name = source_key.service_name; - key.method_name = source_key.method_name; - target_map.insert(std::make_pair(key, source_pair.second)); + target_map.insert(std::make_pair(target_key, source_pair.second)); } } @@ -300,16 +297,8 @@ namespace eCAL QualityTopicInfoMultiMap GetPublishers() { - QualityTopicInfoMultiMap multi_map; - if (g_descgate() == nullptr) return multi_map; - - // insert publisher into target multimap - for (const auto& topic : g_descgate()->GetPublishers()) - { - multi_map.insert(std::pair(topic.first.topic_name, topic.second)); - } - - return multi_map; + if (g_descgate() == nullptr) return QualityTopicInfoMultiMap(); + return g_descgate()->GetPublishers(); } std::set GetPublishers(const std::string& topic_name_) @@ -319,16 +308,8 @@ namespace eCAL QualityTopicInfoMultiMap GetSubscribers() { - QualityTopicInfoMultiMap multi_map; - if (g_descgate() == nullptr) return multi_map; - - // insert subscriber into target multimap - for (const auto& topic : g_descgate()->GetSubscribers()) - { - multi_map.insert(std::pair(topic.first.topic_name, topic.second)); - } - - return multi_map; + if (g_descgate() == nullptr) return QualityTopicInfoMultiMap(); + return g_descgate()->GetSubscribers(); } std::set GetSubscribers(const std::string& topic_name_) @@ -351,35 +332,14 @@ namespace eCAL QualityServiceInfoMultimap GetServices() { - QualityServiceInfoMultimap multi_map; - if (g_descgate() == nullptr) return multi_map; - - // insert services into target multimap - for (const auto& service : g_descgate()->GetServices()) - { - SServiceMethod key; - key.service_name = service.first.service_name; - key.method_name = service.first.method_name; - multi_map.insert(std::pair(key, service.second)); - } - return multi_map; + if (g_descgate() == nullptr) return QualityServiceInfoMultimap(); + return g_descgate()->GetServices(); } QualityServiceInfoMultimap GetClients() { - QualityServiceInfoMultimap multi_map; - if (g_descgate() == nullptr) return multi_map; - - // insert clients into target multimap - for (const auto& client : g_descgate()->GetClients()) - { - SServiceMethod key; - key.service_name = client.first.service_name; - key.method_name = client.first.method_name; - multi_map.insert(std::pair(key, client.second)); - } - - return multi_map; + if (g_descgate() == nullptr) return QualityServiceInfoMultimap(); + return g_descgate()->GetClients(); } SServiceMethodInformation GetHighestQualityServiceMethodInformation(const std::set& quality_service_info_set_) @@ -415,8 +375,8 @@ namespace eCAL quality_topic_info_map_.clear(); if (g_descgate() == nullptr) return; - QualityTopicIdMap pub_sub_map = g_descgate()->GetPublishers(); - QualityTopicIdMap sub_map = g_descgate()->GetSubscribers(); + QualityTopicInfoMultiMap pub_sub_map = g_descgate()->GetPublishers(); + QualityTopicInfoMultiMap sub_map = g_descgate()->GetSubscribers(); pub_sub_map.insert(sub_map.begin(), sub_map.end()); // transform into a map with the highest quality data type information diff --git a/ecal/tests/cpp/descgate_test/src/getpublisher.cpp b/ecal/tests/cpp/descgate_test/src/getpublisher.cpp index 6ab1157a48..c631905c54 100644 --- a/ecal/tests/cpp/descgate_test/src/getpublisher.cpp +++ b/ecal/tests/cpp/descgate_test/src/getpublisher.cpp @@ -116,7 +116,7 @@ TEST(core_cpp_descgate, PublisherQualities) // check pub1 quality { - auto pub_it = sample_map.find({ "pub1", 1 }); + auto pub_it = sample_map.find("pub1"); EXPECT_NE(pub_it, sample_map.end()); if (pub_it != sample_map.end()) { @@ -129,7 +129,7 @@ TEST(core_cpp_descgate, PublisherQualities) // check pub2 quality { - auto pub_it = sample_map.find({ "pub2", 2 }); + auto pub_it = sample_map.find("pub2"); EXPECT_NE(pub_it, sample_map.end()); if (pub_it != sample_map.end()) { @@ -205,7 +205,7 @@ TEST(core_cpp_descgate, SubscriberQualities) // check sub1 quality { - auto sub_it = sample_map.find({ "sub1", 1 }); + auto sub_it = sample_map.find("sub1"); EXPECT_NE(sub_it, sample_map.end()); if (sub_it != sample_map.end()) { @@ -218,7 +218,7 @@ TEST(core_cpp_descgate, SubscriberQualities) // check sub2 quality { - auto sub_it = sample_map.find({ "sub2", 2 }); + auto sub_it = sample_map.find("sub2"); EXPECT_NE(sub_it, sample_map.end()); if (sub_it != sample_map.end()) { From 3c8dd976a03bbb2f6e822604580fa242d82906eb Mon Sep 17 00:00:00 2001 From: rex-schilasky <49162693+rex-schilasky@users.noreply.github.com> Date: Wed, 24 Apr 2024 11:22:27 +0200 Subject: [PATCH 26/27] some additional usings added --- ecal/core/include/ecal/ecal_util.h | 11 ++++++----- ecal/core/src/ecal_util.cpp | 8 ++++---- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/ecal/core/include/ecal/ecal_util.h b/ecal/core/include/ecal/ecal_util.h index 34976c9a56..7cfc6d2b04 100644 --- a/ecal/core/include/ecal/ecal_util.h +++ b/ecal/core/include/ecal/ecal_util.h @@ -68,6 +68,7 @@ namespace eCAL } }; using QualityTopicInfoMultiMap = std::multimap; + using QualityTopicInfoSet = std::set; using ServiceId = std::uint64_t; struct SQualityServiceInfo @@ -93,7 +94,7 @@ namespace eCAL } }; using QualityServiceInfoMultimap = std::multimap; - + using SQualityServiceInfoSet = std::set; /** * @brief Retrieve eCAL configuration path. * This is path is for the global eCAL configuration files @@ -192,7 +193,7 @@ namespace eCAL * * @return Set containing the quality datatype information for this publisher. **/ - ECAL_API std::set GetPublishers(const std::string& topic_name_); + ECAL_API QualityTopicInfoSet GetPublishers(const std::string& topic_name_); /** * @brief Get complete snapshot of data type information with quality and topic id for all known subscribers. @@ -208,7 +209,7 @@ namespace eCAL * * @return Set containing the quality datatype information for this subscriber. **/ - ECAL_API std::set GetSubscribers(const std::string& topic_name_); + ECAL_API QualityTopicInfoSet GetSubscribers(const std::string& topic_name_); /** * @brief Get highest quality data type information out of a set of quality data type information. @@ -217,7 +218,7 @@ namespace eCAL * * @return Highest quality data type information. **/ - ECAL_API SDataTypeInformation GetHighestQualityDataTypeInformation(const std::set& quality_topic_info_set_); + ECAL_API SDataTypeInformation GetHighestQualityDataTypeInformation(const QualityTopicInfoSet& quality_topic_info_set_); /** * @brief Get complete snapshot of service method information with quality and service id for all known services. @@ -240,7 +241,7 @@ namespace eCAL * * @return Highest quality service method information. **/ - ECAL_API SServiceMethodInformation GetHighestQualityServiceMethodInformation(const std::set& quality_service_info_set_); + ECAL_API SServiceMethodInformation GetHighestQualityServiceMethodInformation(const SQualityServiceInfoSet& quality_service_info_set_); /** * @brief Get complete topic map. diff --git a/ecal/core/src/ecal_util.cpp b/ecal/core/src/ecal_util.cpp index c8f00afdc3..3bb2047e2d 100644 --- a/ecal/core/src/ecal_util.cpp +++ b/ecal/core/src/ecal_util.cpp @@ -301,7 +301,7 @@ namespace eCAL return g_descgate()->GetPublishers(); } - std::set GetPublishers(const std::string& topic_name_) + QualityTopicInfoSet GetPublishers(const std::string& topic_name_) { return ::GetQualityTopicInfoSet(topic_name_, GetPublishers()); } @@ -312,12 +312,12 @@ namespace eCAL return g_descgate()->GetSubscribers(); } - std::set GetSubscribers(const std::string& topic_name_) + QualityTopicInfoSet GetSubscribers(const std::string& topic_name_) { return ::GetQualityTopicInfoSet(topic_name_, GetSubscribers()); } - SDataTypeInformation GetHighestQualityDataTypeInformation(const std::set& quality_topic_info_set_) + SDataTypeInformation GetHighestQualityDataTypeInformation(const QualityTopicInfoSet& quality_topic_info_set_) { SQualityTopicInfo highest_quality_topic_info; for (const auto& info : quality_topic_info_set_) @@ -342,7 +342,7 @@ namespace eCAL return g_descgate()->GetClients(); } - SServiceMethodInformation GetHighestQualityServiceMethodInformation(const std::set& quality_service_info_set_) + SServiceMethodInformation GetHighestQualityServiceMethodInformation(const SQualityServiceInfoSet& quality_service_info_set_) { SQualityServiceInfo highest_quality_service_info; for (const auto& info : quality_service_info_set_) From d4769e5e2c67b1bab51966c2ca667c31fcf9d9e6 Mon Sep 17 00:00:00 2001 From: rex-schilasky <49162693+rex-schilasky@users.noreply.github.com> Date: Wed, 24 Apr 2024 14:04:36 +0200 Subject: [PATCH 27/27] SServiceIdKey compare operator improved --- ecal/core/src/ecal_descgate.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ecal/core/src/ecal_descgate.h b/ecal/core/src/ecal_descgate.h index 7052797288..c91b854be3 100644 --- a/ecal/core/src/ecal_descgate.h +++ b/ecal/core/src/ecal_descgate.h @@ -56,7 +56,7 @@ namespace eCAL bool operator<(const SServiceIdKey& other) const { - return std::tie(service_name, service_id) < std::tie(other.service_name, other.service_id); + return std::tie(service_name, method_name, service_id) < std::tie(other.service_name, other.method_name, other.service_id); } };