Program Listing for File topic_cache.hpp
↰ Return to documentation for file (/tmp/ws/src/rmw_gurumdds/rmw_gurumdds_shared_cpp/include/rmw_gurumdds_shared_cpp/topic_cache.hpp
)
// Copyright 2019 GurumNetworks, Inc.
//
// 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.
#ifndef RMW_GURUMDDS_SHARED_CPP__TOPIC_CACHE_HPP_
#define RMW_GURUMDDS_SHARED_CPP__TOPIC_CACHE_HPP_
#include <algorithm>
#include <iterator>
#include <map>
#include <mutex>
#include <set>
#include <sstream>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
#include "rcutils/logging_macros.h"
#include "rmw/types.h"
typedef std::map<std::string, std::set<std::string>> TopicsTypes;
template<typename GUID_t>
class TopicCache
{
public:
struct TopicInfo
{
GUID_t participant_guid;
GUID_t entity_guid;
std::string name;
std::string type;
rmw_qos_profile_t qos;
};
typedef std::map<GUID_t, std::multiset<GUID_t>> ParticipantToEntityGuidMap;
typedef std::map<GUID_t, TopicInfo> EntityGuidToInfo;
typedef std::unordered_map<std::string, std::vector<TopicInfo>> TopicNameToInfo;
const EntityGuidToInfo & get_entity_guid_to_info() const
{
return entity_guid_to_info_;
}
const ParticipantToEntityGuidMap & get_participant_to_entity_guid_map() const
{
return participant_to_entity_guids_;
}
const TopicNameToInfo get_topic_name_to_info() const
{
TopicNameToInfo tnti;
for (auto & i : entity_guid_to_info_) {
tnti[i.second.name].push_back(i.second);
}
return tnti;
}
bool add_topic(
const GUID_t & participant_guid,
const GUID_t & entity_guid,
std::string && topic_name,
std::string && type_name,
rmw_qos_profile_t & qos)
{
initialize_participant_map(participant_to_entity_guids_, participant_guid);
if (rcutils_logging_logger_is_enabled_for(
"rmw_gurumdds_shared_cpp", RCUTILS_LOG_SEVERITY_DEBUG))
{
std::stringstream guid_stream;
guid_stream << participant_guid;
RCUTILS_LOG_DEBUG_NAMED(
"rmw_gurumdds_shared_cpp",
"Adding topic '%s' with type '%s' for node '%s'",
topic_name.c_str(), type_name.c_str(), guid_stream.str().c_str());
}
auto topic_info_it = entity_guid_to_info_.find(entity_guid);
if (topic_info_it != entity_guid_to_info_.end()) {
RCUTILS_LOG_DEBUG_NAMED(
"rmw_gurumdds_shared_cpp",
"unique topic '%s' with type '%s' attempted to be added twice, ignoring",
topic_name.c_str(), type_name.c_str());
return false;
}
entity_guid_to_info_[entity_guid] =
TopicInfo {participant_guid, entity_guid, std::move(topic_name), std::move(type_name), qos};
participant_to_entity_guids_[participant_guid].insert(entity_guid);
return true;
}
bool add_topic(
const GUID_t & participant_guid,
const GUID_t & entity_guid,
const std::string & topic_name,
const std::string & type_name,
rmw_qos_profile_t & qos)
{
return add_topic(
participant_guid, entity_guid, std::string(topic_name),
std::string(type_name), qos);
}
bool get_topic(const GUID_t & entity_guid, TopicInfo & topic_info) const
{
auto topic_info_it = entity_guid_to_info_.find(entity_guid);
if (topic_info_it == entity_guid_to_info_.end()) {
RCUTILS_LOG_DEBUG_NAMED(
"rmw_gurumdds_shared_cpp",
"topic not available");
return false;
}
topic_info = topic_info_it->second;
return true;
}
int remove_topic_by_puid(const GUID_t & participant_guid)
{
int removed_topic_count = 0;
auto participant_to_entity_guid = participant_to_entity_guids_.find(participant_guid);
if (participant_to_entity_guid == participant_to_entity_guids_.end()) {
return -1;
}
for (auto & entity_guid : participant_to_entity_guid->second) {
auto topic_info_iter = entity_guid_to_info_.find(entity_guid);
if (topic_info_iter == entity_guid_to_info_.end()) {
continue;
}
entity_guid_to_info_.erase(topic_info_iter);
removed_topic_count++;
}
participant_to_entity_guid->second.clear();
if (participant_to_entity_guid->second.empty()) {
participant_to_entity_guids_.erase(participant_to_entity_guid);
}
return removed_topic_count;
}
bool remove_topic(const GUID_t & entity_guid)
{
auto topic_info_it = entity_guid_to_info_.find(entity_guid);
if (topic_info_it == entity_guid_to_info_.end()) {
RCUTILS_LOG_DEBUG_NAMED(
"rmw_gurumdds_shared_cpp",
"unexpected topic removal");
return false;
}
std::string & topic_name = topic_info_it->second.name;
std::string & type_name = topic_info_it->second.type;
auto & participant_guid = topic_info_it->second.participant_guid;
auto participant_to_entity_guid = participant_to_entity_guids_.find(participant_guid);
if (participant_to_entity_guid == participant_to_entity_guids_.end()) {
RCUTILS_LOG_WARN_NAMED(
"rmw_gurumdds_shared_cpp",
"unable to remove topic, "
"participant guid does not exist for topic name '%s' with type '%s'",
topic_name.c_str(), type_name.c_str());
return false;
}
auto entity_guid_to_remove = participant_to_entity_guid->second.find(entity_guid);
if (entity_guid_to_remove == participant_to_entity_guid->second.end()) {
RCUTILS_LOG_WARN_NAMED(
"rmw_gurumdds_shared_cpp",
"unable to remove topic, "
"topic guid does not exist in participant guid: topic name '%s' with type '%s'",
topic_name.c_str(), type_name.c_str());
return false;
}
entity_guid_to_info_.erase(topic_info_it);
participant_to_entity_guid->second.erase(entity_guid_to_remove);
if (participant_to_entity_guid->second.empty()) {
participant_to_entity_guids_.erase(participant_to_entity_guid);
}
return true;
}
TopicsTypes get_topic_types_by_guid(const GUID_t & participant_guid)
{
TopicsTypes topics_types;
const auto participant_to_entity_guids = participant_to_entity_guids_.find(participant_guid);
if (participant_to_entity_guids == participant_to_entity_guids_.end()) {
return topics_types;
}
for (auto & entity_guid : participant_to_entity_guids->second) {
auto topic_info = entity_guid_to_info_.find(entity_guid);
if (topic_info == entity_guid_to_info_.end()) {
continue;
}
auto & topic_name = topic_info->second.name;
topics_types[topic_name].insert(topic_info->second.type);
}
return topics_types;
}
void clear_cache(void)
{
entity_guid_to_info_.clear();
participant_to_entity_guids_.clear();
}
private:
EntityGuidToInfo entity_guid_to_info_;
ParticipantToEntityGuidMap participant_to_entity_guids_;
void initialize_participant_map(ParticipantToEntityGuidMap & map, const GUID_t & participant_guid)
{
if (map.find(participant_guid) == map.end()) {
map[participant_guid] = std::multiset<GUID_t>();
}
}
};
#endif // RMW_GURUMDDS_SHARED_CPP__TOPIC_CACHE_HPP_