Skip to content

Commit

Permalink
Refs #21458: Add type IDL to Topic info json [WORK IN PROGRESS]
Browse files Browse the repository at this point in the history
Signed-off-by: Carlosespicur <[email protected]>
  • Loading branch information
Carlosespicur committed Aug 7, 2024
1 parent a885a58 commit ee80c44
Show file tree
Hide file tree
Showing 8 changed files with 165 additions and 9 deletions.
1 change: 1 addition & 0 deletions examples/cpp/HelloWorldExample/Monitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,7 @@ void Monitor::Listener::on_topic_discovery(
EntityId topic_id,
const DomainListener::Status& status)
{

static_cast<void>(domain_id);
Info topic_info = StatisticsBackend::get_info(topic_id);

Expand Down
2 changes: 2 additions & 0 deletions include/fastdds_statistics_backend/types/JSONTags.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ constexpr const char* METATRAFFIC_TAG = "metatraffic";
constexpr const char* PID_TAG = "pid";
//! Key tag for type name of a topic entity
constexpr const char* DATA_TYPE_TAG = "data_type";
//! Key tag for IDL representation of a data type
constexpr const char* DATA_TYPE_IDL_TAG = "data_type_idl";
//! Key tag for GUID of a participant, datawriter or datareader entity
constexpr const char* GUID_TAG = "guid";
//! Key tag for QoS of a participant, datawriter or datareader entity
Expand Down
57 changes: 54 additions & 3 deletions src/cpp/database/database.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ EntityId Database::insert_new_topic(
std::shared_ptr<Domain> domain = std::const_pointer_cast<Domain>(
std::static_pointer_cast<const Domain>(get_entity_nts(domain_id)));

// Create the topic to insert in the database
auto topic = std::make_shared<Topic>(
name,
type_name,
Expand All @@ -279,6 +280,33 @@ EntityId Database::insert_new_topic(
return entity_id;
}

bool Database::is_type_in_database(
const std::string& type_name)
{

if (type_idls_.find(type_name) != type_idls_.end())
{
return true;
}
else
{
return false;
}
}

void Database::insert_new_type_idl(
const std::string& type_name,
const std::string& type_idl)
{
std::lock_guard<std::shared_timed_mutex> guard(mutex_);
if (type_name.empty() || type_idl.empty())
{
throw BadParameter("Type name or type IDL cannot be empty");
}
type_idls_[type_name] = type_idl;
}


EntityId Database::insert_new_endpoint(
const std::string& endpoint_guid,
const std::string& name,
Expand Down Expand Up @@ -656,7 +684,7 @@ void Database::insert_nts(
throw BadParameter("Topic data type cannot be empty");
}

/* Check that domain exits */
/* Check that domain exists */
bool domain_exists = false;
for (const auto& domain_it : domains_)
{
Expand Down Expand Up @@ -2103,6 +2131,22 @@ std::vector<std::pair<EntityId, EntityId>> Database::get_entities_by_name_nts(
return entities;
}

std::string Database::get_type_idl(const std::string& type_name) const
{
std::shared_lock<std::shared_timed_mutex> lock(mutex_);
return get_type_idl_nts(type_name);
}

std::string Database::get_type_idl_nts(const std::string& type_name) const
{
auto it = type_idls_.find(type_name);
if (it != type_idls_.end())
{
return it->second;
}
throw BadParameter("Type " + type_name + " not found in the database");
}

void Database::erase(
EntityId& domain_id)
{
Expand Down Expand Up @@ -4623,8 +4667,8 @@ DatabaseDump Database::dump_entity_(
entity_info[NAME_TAG] = entity->name;
entity_info[ALIAS_TAG] = entity->alias;
entity_info[DATA_TYPE_TAG] = entity->data_type;
entity_info[DATA_TYPE_IDL_TAG] = get_type_idl(entity->data_type);
entity_info[STATUS_TAG] = entity->status;

entity_info[DOMAIN_ENTITY_TAG] = id_to_string(entity->domain->id);

// metatraffic and active attributes are stored but ignored when loading
Expand Down Expand Up @@ -5245,6 +5289,11 @@ Info Database::get_info(
std::shared_ptr<const Topic> topic =
std::dynamic_pointer_cast<const Topic>(entity);
info[DATA_TYPE_TAG] = topic->data_type;
// Add IDL representation of the data type if available
if (is_type_in_database(topic->data_type))
{
info[DATA_TYPE_IDL_TAG] = get_type_idl(topic->data_type);
}
break;
}
case EntityKind::PARTICIPANT:
Expand Down Expand Up @@ -5303,8 +5352,10 @@ Info Database::get_info(
break;
}
}

// __FLAG__
std::cout << "Info:" << info << std::endl;
return info;

}

void Database::check_entity_kinds(
Expand Down
47 changes: 47 additions & 0 deletions src/cpp/database/database.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ class Database
const std::string& topic_type,
const EntityId& topic_id);


/**
* @brief Create new Topic and insert it in database.
* @param name The name of the Topic.
Expand All @@ -156,6 +157,24 @@ class Database
const std::string& alias,
const EntityId& domain_id);

/**
* @brief Check if a Topic data type is already in the database
* @param type_name The type name of the Topic.
*
* @return True if the Topic data type is in the database.
*/
bool is_type_in_database(
const std::string& type_name);

/**
* @brief Insert a new type IDL into the database.
* @param topic_type The type of the topic.
* @param topic_idl The IDL representation of the type
*/
void insert_new_type_idl(
const std::string& topic_type,
const std::string& topic_idl);

/**
* @brief Create new Endpoint and corresponding Locator, and insert them in database.
* @param endpoint_guid The GUID of the Endpoint.
Expand Down Expand Up @@ -444,6 +463,16 @@ class Database
EntityKind entity_kind,
const std::string& name) const;

/**
* @brief Get the type IDL of a given type name, if it exists.
*
* @param type_name The name of the data type for which to search.
* @throws eprosima::statistics_backend::BadParameter if \c type_name does not exist in the database.
* @return The IDL representation of the type in std::string format.
*/
std::string get_type_idl(
const std::string& type_name) const;

/**
* @brief Get the entity of a given EntityKind that matches with the requested GUID.
*
Expand Down Expand Up @@ -1167,6 +1196,16 @@ class Database
EntityKind entity_kind,
const std::string& name) const;

/**
* @brief Get the type IDL of a given type name, if it exists. This method is not thread safe.
*
* @param type_name The name of the data type for which to search.
* @throws eprosima::statistics_backend::BadParameter if \c type_name does not exist in the database.
* @return The IDL representation of the type in std::string format.
*/
std::string get_type_idl_nts(
const std::string& type_name) const;

/**
* @brief Get the entity of a given EntityKind that matches with the requested GUID. This method is not thread safe.
*
Expand Down Expand Up @@ -1446,6 +1485,14 @@ class Database
*/
std::map<EntityId, std::map<EntityId, std::shared_ptr<Topic>>> topics_;

/**
* Collection of topic IDLs sorted by topic data types, with which they are biunivocally identified.
* This is used to store the IDLs of the discovered topics
*
* Each value in the collection is in turn a map of the actual Topic IDLs sorted by data type
*/
std::map<std::string, std::string> type_idls_;

//! Graph map describing per domain complete topology of the entities.
std::map<EntityId, Graph> domain_view_graph;

Expand Down
11 changes: 8 additions & 3 deletions src/cpp/database/database_queue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ namespace statistics_backend {
namespace database {

using namespace eprosima::fastdds::dds;
using namespace eprosima::fastdds::
rtps;
using namespace eprosima::fastdds::rtps;

template<typename T>
std::string to_string(
Expand Down Expand Up @@ -130,7 +129,7 @@ EntityId DatabaseEntityQueue::process_participant(
{
process_name = info.process;
process_pid = info.process;
logInfo(BACKEND_DATABASE,
EPROSIMA_LOG_INFO(BACKEND_DATABASE,
"Process name " + process_name + " does not follow the [command]:[PID] pattern");
}
else
Expand Down Expand Up @@ -363,6 +362,12 @@ EntityId DatabaseEntityQueue::process_endpoint_discovery(
details::StatisticsBackendData::DiscoveryStatus::DISCOVERY);
}

// Store type IDL in the database in case it is not already stored. Ignore metatraffic topics
if (!database_->is_type_in_database(info.type_name) && !info.is_virtual_metatraffic)
{
database_->insert_new_type_idl(info.type_name, info.type_idl);
}

// Create the endpoint
EntityId endpoint_id;
std::stringstream name;
Expand Down
4 changes: 2 additions & 2 deletions src/cpp/database/database_queue.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
#include <fastdds/rtps/common/SequenceNumber.hpp>
#include <fastdds/rtps/common/RemoteLocators.hpp>
#include <fastdds/dds/log/Log.hpp>

#include <fastdds_statistics_backend/types/JSONTags.h>

#include <database/database.hpp>
Expand Down Expand Up @@ -372,9 +371,10 @@ struct EntityDiscoveryInfo
std::string user;
std::string process;

// Enpoint data
// Endpoint data
std::string topic_name;
std::string type_name;
std::string type_idl;
fastdds::rtps::RemoteLocatorList locators;

// Alias
Expand Down
47 changes: 46 additions & 1 deletion src/cpp/subscriber/StatisticsParticipantListener.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,14 @@

#include <fastdds/dds/core/status/StatusMask.hpp>
#include <fastdds/dds/domain/DomainParticipant.hpp>
#include <fastdds/dds/domain/DomainParticipantFactory.hpp>
#include <fastdds/dds/domain/DomainParticipantListener.hpp>
#include <fastdds/dds/log/Log.hpp>
#include <fastdds/rtps/writer/WriterDiscoveryStatus.hpp>
#include <fastdds/dds/xtypes/dynamic_types/DynamicTypeBuilder.hpp>
#include <fastdds/dds/xtypes/dynamic_types/DynamicTypeBuilderFactory.hpp>
#include <fastdds/dds/xtypes/utils.hpp>
#include <fastdds/rtps/common/EntityId_t.hpp>
#include <fastdds/rtps/writer/WriterDiscoveryStatus.hpp>

#include "database/database_queue.hpp"
#include "subscriber/QosSerializer.hpp"
Expand Down Expand Up @@ -320,12 +324,34 @@ void StatisticsParticipantListener::on_data_reader_discovery(
}
}

// Create IDL representation of the discovered type
// Get remote type information
xtypes::TypeObject remote_type_object;
if (RETCODE_OK != DomainParticipantFactory::get_instance()->type_object_registry().get_type_object(
info.type_information.type_information.complete().typeid_with_size().type_id(),
remote_type_object))
{
// Error
return;
}

// Build remotely discovered type
DynamicType::_ref_type remote_type = DynamicTypeBuilderFactory::get_instance()->create_type_w_type_object(
remote_type_object)->build();

// Serialize DynamicType into its IDL representation
std::stringstream idl;
idl_serialize(remote_type, idl);
discovery_info.type_idl = idl.str();

entity_queue_->push(timestamp, discovery_info);

// Wait until the entity queue is processed and restart the data queues
entity_queue_->flush();
data_queue_->start_consumer();
monitor_service_status_data_queue_->start_consumer();


}

void StatisticsParticipantListener::on_data_writer_discovery(
Expand Down Expand Up @@ -377,6 +403,25 @@ void StatisticsParticipantListener::on_data_writer_discovery(
break;
}
}
// Create IDL representation of the discovered type
// Get remote type information
xtypes::TypeObject remote_type_object;
if (RETCODE_OK != DomainParticipantFactory::get_instance()->type_object_registry().get_type_object(
info.type_information.type_information.complete().typeid_with_size().type_id(),
remote_type_object))
{
// Error
return;
}

// Build remotely discovered type
DynamicType::_ref_type remote_type = DynamicTypeBuilderFactory::get_instance()->create_type_w_type_object(
remote_type_object)->build();

// Serialize DynamicType into its IDL representation
std::stringstream idl;
idl_serialize(remote_type, idl);
discovery_info.type_idl = idl.str();

entity_queue_->push(timestamp, discovery_info);

Expand Down
5 changes: 5 additions & 0 deletions test/mock/database/database/database/database.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ class Database
MOCK_METHOD2(is_topic_in_database, bool(
const std::string& topic_type,
const EntityId& topic_id));
MOCK_METHOD1(is_type_in_database, bool(
const std::string& type_name));
MOCK_METHOD2(insert_new_type_idl, void(
const std::string& type_name,
const std::string& type_idl));

MOCK_METHOD4(insert_new_topic, EntityId(
const std::string& name,
Expand Down

0 comments on commit ee80c44

Please sign in to comment.