Skip to content

Commit 44d4f81

Browse files
authored
Add xml dynamic types participant (#164)
* Add xml dynamic types participant Signed-off-by: Raul Sanchez-Mateos <raul@eprosima.com> * Add code documentation Signed-off-by: Raul Sanchez-Mateos <raul@eprosima.com> --------- Signed-off-by: Raul Sanchez-Mateos <raul@eprosima.com>
1 parent 13b7e0d commit 44d4f81

2 files changed

Lines changed: 356 additions & 0 deletions

File tree

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
// Copyright 2023 Proyectos y Sistemas de Mantenimiento SL (eProsima).
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
/**
16+
* @file XmlDynTypesParticipant.hpp
17+
* @brief Defines the XmlDynTypesParticipant class for routing dynamic types in DDS.
18+
*/
19+
20+
#pragma once
21+
22+
#include <memory>
23+
#include <set>
24+
25+
#include <fastcdr/cdr/fixed_size_string.hpp>
26+
27+
#include <fastdds/dds/domain/DomainParticipant.hpp>
28+
#include <fastdds/dds/xtypes/dynamic_types/DynamicType.hpp>
29+
#include <fastdds/dds/xtypes/type_representation/detail/dds_xtypes_typeobject.hpp>
30+
#include <fastdds/rtps/builtin/data/PublicationBuiltinTopicData.hpp>
31+
#include <fastdds/rtps/builtin/data/SubscriptionBuiltinTopicData.hpp>
32+
#include <fastdds/rtps/participant/RTPSParticipant.hpp>
33+
#include <fastdds/rtps/reader/ReaderDiscoveryStatus.hpp>
34+
#include <fastdds/rtps/writer/WriterDiscoveryStatus.hpp>
35+
36+
#include <ddspipe_participants/configuration/XmlParticipantConfiguration.hpp>
37+
#include <ddspipe_participants/library/library_dll.h>
38+
#include <ddspipe_participants/participant/dds/XmlParticipant.hpp>
39+
#include <ddspipe_participants/reader/auxiliar/InternalReader.hpp>
40+
41+
namespace eprosima {
42+
namespace ddspipe {
43+
namespace participants {
44+
45+
/**
46+
* @class XmlDynTypesParticipant
47+
* @brief A specialized RTPS participant capable of routing dynamic types and user data.
48+
*/
49+
class XmlDynTypesParticipant : public dds::XmlParticipant
50+
{
51+
public:
52+
53+
/**
54+
* @brief Constructs an XmlDynTypesParticipant.
55+
*
56+
* @param participant_configuration Shared pointer to the participant configuration.
57+
* @param payload_pool Shared pointer to the payload pool.
58+
* @param discovery_database Shared pointer to the discovery database.
59+
*/
60+
DDSPIPE_PARTICIPANTS_DllAPI
61+
XmlDynTypesParticipant(
62+
std::shared_ptr<XmlParticipantConfiguration> participant_configuration,
63+
std::shared_ptr<core::PayloadPool> payload_pool,
64+
std::shared_ptr<core::DiscoveryDatabase> discovery_database);
65+
66+
/**
67+
* @brief Creates a writer object based on the topic QoS.
68+
*
69+
* @param topic The topic for which the writer is created.
70+
* @return A shared pointer to the created writer.
71+
*/
72+
DDSPIPE_PARTICIPANTS_DllAPI
73+
std::shared_ptr<core::IWriter> create_writer(
74+
const core::ITopic& topic) override;
75+
76+
/**
77+
* @brief Creates a reader object based on the topic QoS.
78+
*
79+
* @param topic The topic for which the reader is created.
80+
* @return A shared pointer to the created reader.
81+
*/
82+
DDSPIPE_PARTICIPANTS_DllAPI
83+
std::shared_ptr<core::IReader> create_reader(
84+
const core::ITopic& topic) override;
85+
86+
/**
87+
* @class XmlDynTypesDdsListener
88+
* @brief Listener for handling DDS discovery events for dynamic types.
89+
*/
90+
class XmlDynTypesDdsListener : public dds::CommonParticipant::DdsListener
91+
{
92+
public:
93+
94+
/**
95+
* @brief Constructs an XmlDynTypesDdsListener.
96+
*
97+
* @param conf Shared pointer to the participant configuration.
98+
* @param ddb Shared pointer to the discovery database.
99+
* @param internal_reader Shared pointer to the internal reader.
100+
*/
101+
DDSPIPE_PARTICIPANTS_DllAPI
102+
explicit XmlDynTypesDdsListener(
103+
std::shared_ptr<SimpleParticipantConfiguration> conf,
104+
std::shared_ptr<core::DiscoveryDatabase> ddb,
105+
std::shared_ptr<InternalReader> internal_reader);
106+
107+
/**
108+
* @brief Callback for data reader discovery events.
109+
*
110+
* @param participant The domain participant.
111+
* @param reason The discovery reason.
112+
* @param info The discovered subscription information.
113+
* @param should_be_ignored Whether the reader should be ignored.
114+
*/
115+
DDSPIPE_PARTICIPANTS_DllAPI
116+
void on_data_reader_discovery(
117+
fastdds::dds::DomainParticipant* participant,
118+
fastdds::rtps::ReaderDiscoveryStatus reason,
119+
const fastdds::dds::SubscriptionBuiltinTopicData& info,
120+
bool& /*should_be_ignored*/) override;
121+
122+
/**
123+
* @brief Callback for data writer discovery events.
124+
*
125+
* @param participant The domain participant.
126+
* @param reason The discovery reason.
127+
* @param info The discovered publication information.
128+
* @param should_be_ignored Whether the writer should be ignored.
129+
*/
130+
DDSPIPE_PARTICIPANTS_DllAPI
131+
void on_data_writer_discovery(
132+
fastdds::dds::DomainParticipant* participant,
133+
fastdds::rtps::WriterDiscoveryStatus reason,
134+
const fastdds::dds::PublicationBuiltinTopicData& info,
135+
bool& /*should_be_ignored*/) override;
136+
137+
protected:
138+
139+
/// Internal reader for type objects.
140+
std::shared_ptr<InternalReader> type_object_reader_;
141+
142+
/// Set of received types.
143+
std::set<std::string> received_types_;
144+
145+
/**
146+
* @brief Notifies that a type has been discovered.
147+
*
148+
* @param type_info The discovered type information.
149+
* @param type_name The name of the discovered type.
150+
*/
151+
void notify_type_discovered_(
152+
const fastdds::dds::xtypes::TypeInformation& type_info,
153+
const std::string& type_name);
154+
};
155+
156+
protected:
157+
158+
/**
159+
* @brief Creates the internal RTPS participant listener.
160+
*
161+
* @return A unique pointer to the created listener.
162+
*/
163+
DDSPIPE_PARTICIPANTS_DllAPI
164+
std::unique_ptr<fastdds::dds::DomainParticipantListener> create_listener_() override;
165+
166+
/// Internal reader for type objects.
167+
std::shared_ptr<InternalReader> type_object_reader_;
168+
};
169+
170+
} /* namespace participants */
171+
} /* namespace ddspipe */
172+
} /* namespace eprosima */
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
// Copyright 2023 Proyectos y Sistemas de Mantenimiento SL (eProsima).
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
/**
16+
* @file XmlDynTypesParticipant.cpp
17+
*/
18+
19+
#include <memory>
20+
21+
#include <fastdds/dds/domain/DomainParticipantFactory.hpp>
22+
#include <fastdds/dds/xtypes/dynamic_types/DynamicTypeBuilder.hpp>
23+
#include <fastdds/dds/xtypes/dynamic_types/DynamicTypeBuilderFactory.hpp>
24+
#include <fastdds/dds/xtypes/type_representation/TypeObject.hpp>
25+
#include <fastdds/rtps/attributes/RTPSParticipantAttributes.hpp>
26+
#include <fastdds/rtps/RTPSDomain.hpp>
27+
28+
#include <cpp_utils/Log.hpp>
29+
30+
#include <ddspipe_core/monitoring/producers/TopicsMonitorProducer.hpp>
31+
#include <ddspipe_core/types/dynamic_types/types.hpp>
32+
#include <ddspipe_participants/reader/auxiliar/BlankReader.hpp>
33+
#include <ddspipe_participants/reader/rtps/SpecificQoSReader.hpp>
34+
#include <ddspipe_participants/writer/auxiliar/BlankWriter.hpp>
35+
36+
#include <ddspipe_participants/participant/dynamic_types/XmlDynTypesParticipant.hpp>
37+
38+
namespace eprosima {
39+
namespace ddspipe {
40+
namespace participants {
41+
42+
using namespace eprosima::ddspipe::core;
43+
44+
XmlDynTypesParticipant::XmlDynTypesParticipant(
45+
std::shared_ptr<XmlParticipantConfiguration> participant_configuration,
46+
std::shared_ptr<PayloadPool> payload_pool,
47+
std::shared_ptr<DiscoveryDatabase> discovery_database)
48+
: XmlParticipant(
49+
participant_configuration,
50+
payload_pool,
51+
discovery_database)
52+
, type_object_reader_(std::make_shared<InternalReader>(
53+
this->id()))
54+
{
55+
// Do nothing
56+
}
57+
58+
std::shared_ptr<IWriter> XmlDynTypesParticipant::create_writer(
59+
const ITopic& topic)
60+
{
61+
// This participant does not write anything
62+
return std::make_shared<BlankWriter>();
63+
}
64+
65+
std::shared_ptr<IReader> XmlDynTypesParticipant::create_reader(
66+
const ITopic& topic)
67+
{
68+
// If type object topic, return the internal reader for type objects
69+
if (core::types::is_type_object_topic(topic))
70+
{
71+
return type_object_reader_;
72+
}
73+
74+
// If not type object, use the parent method
75+
return dds::XmlParticipant::create_reader(topic);
76+
}
77+
78+
XmlDynTypesParticipant::XmlDynTypesDdsListener::XmlDynTypesDdsListener(
79+
std::shared_ptr<SimpleParticipantConfiguration> conf,
80+
std::shared_ptr<core::DiscoveryDatabase> ddb,
81+
std::shared_ptr<InternalReader> internal_reader)
82+
: dds::CommonParticipant::DdsListener(conf, ddb)
83+
, type_object_reader_(internal_reader)
84+
{
85+
}
86+
87+
void XmlDynTypesParticipant::XmlDynTypesDdsListener::on_data_reader_discovery(
88+
fastdds::dds::DomainParticipant* participant,
89+
fastdds::rtps::ReaderDiscoveryStatus reason,
90+
const fastdds::dds::SubscriptionBuiltinTopicData& info,
91+
bool& should_be_ignored)
92+
{
93+
if (info.guid.guidPrefix != participant->guid().guidPrefix)
94+
{
95+
// Get type information
96+
const auto type_info = info.type_information.type_information;
97+
const auto type_name = info.type_name.to_string();
98+
99+
dds::CommonParticipant::DdsListener::on_data_reader_discovery(participant, reason, info, should_be_ignored);
100+
101+
notify_type_discovered_(type_info, type_name);
102+
}
103+
}
104+
105+
void XmlDynTypesParticipant::XmlDynTypesDdsListener::on_data_writer_discovery(
106+
fastdds::dds::DomainParticipant* participant,
107+
fastdds::rtps::WriterDiscoveryStatus reason,
108+
const fastdds::dds::PublicationBuiltinTopicData& info,
109+
bool& should_be_ignored)
110+
{
111+
if (info.guid.guidPrefix != participant->guid().guidPrefix)
112+
{
113+
// Get type information
114+
const auto type_info = info.type_information.type_information;
115+
const auto type_name = info.type_name.to_string();
116+
117+
dds::CommonParticipant::DdsListener::on_data_writer_discovery(participant, reason, info, should_be_ignored);
118+
119+
notify_type_discovered_(type_info, type_name);
120+
}
121+
}
122+
123+
void XmlDynTypesParticipant::XmlDynTypesDdsListener::notify_type_discovered_(
124+
const fastdds::dds::xtypes::TypeInformation& type_info,
125+
const std::string& type_name)
126+
{
127+
// Check if it exists already
128+
if (received_types_.find(type_name) != received_types_.end())
129+
{
130+
EPROSIMA_LOG_INFO(DDSPIPE_DYNTYPES_PARTICIPANT,
131+
"Type " << type_name << " was already received, aborting propagation.");
132+
return;
133+
}
134+
135+
const auto type_identifier = type_info.complete().typeid_with_size().type_id();
136+
fastdds::dds::xtypes::TypeObject dyn_type_object;
137+
if (fastdds::dds::RETCODE_OK !=
138+
fastdds::dds::DomainParticipantFactory::get_instance()->type_object_registry().get_type_object(
139+
type_identifier,
140+
dyn_type_object))
141+
{
142+
EPROSIMA_LOG_INFO(DDSPIPE_DYNTYPES_PARTICIPANT,
143+
"Failed to get type object of " << type_name << " type");
144+
return;
145+
}
146+
147+
// Create Dynamic Type
148+
fastdds::dds::DynamicType::_ref_type dyn_type =
149+
fastdds::dds::DynamicTypeBuilderFactory::get_instance()->create_type_w_type_object(
150+
dyn_type_object)->build();
151+
if (!dyn_type)
152+
{
153+
EPROSIMA_LOG_WARNING(DDSPIPE_DYNTYPES_PARTICIPANT,
154+
"Failed to create Dynamic Type " << type_name);
155+
return;
156+
}
157+
158+
// Notify type_identifier
159+
// NOTE: We assume each type_name corresponds to only one type_identifier
160+
EPROSIMA_LOG_INFO(DDSPIPE_DYNTYPES_PARTICIPANT,
161+
"Participant " << configuration_->id << " discovered type object " << dyn_type->get_name());
162+
163+
monitor_type_discovered(type_name);
164+
165+
// If not, add it to the received types set
166+
received_types_.insert(type_name);
167+
168+
// Create data containing Dynamic Type
169+
auto data = std::make_unique<core::types::DynamicTypeData>();
170+
data->dynamic_type = dyn_type; // TODO: add constructor with param
171+
data->type_identifier = type_identifier;
172+
173+
// Insert new data in internal reader queue
174+
type_object_reader_->simulate_data_reception(std::move(data));
175+
}
176+
177+
std::unique_ptr<fastdds::dds::DomainParticipantListener> XmlDynTypesParticipant::create_listener_()
178+
{
179+
return std::make_unique<XmlDynTypesDdsListener>(configuration_, discovery_database_, type_object_reader_);
180+
}
181+
182+
} /* namespace participants */
183+
} /* namespace ddspipe */
184+
} /* namespace eprosima */

0 commit comments

Comments
 (0)