Skip to content

Commit bdd0d6d

Browse files
Support repeater feature in DDS (XML) participants
Signed-off-by: Juan Lopez Fernandez <juanlopez@eprosima.com>
1 parent d0008a6 commit bdd0d6d

15 files changed

Lines changed: 307 additions & 31 deletions

File tree

ddspipe_participants/include/ddspipe_participants/writer/dds/CommonWriter.hpp

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@
2020
#include <fastdds/dds/publisher/DataWriter.hpp>
2121
#include <fastdds/dds/publisher/Publisher.hpp>
2222
#include <fastdds/dds/publisher/qos/DataWriterQos.hpp>
23+
#include <fastdds/dds/topic/IContentFilter.hpp>
2324
#include <fastdds/dds/topic/Topic.hpp>
25+
#include <fastdds/rtps/common/WriteParams.hpp>
2426

2527
#include <ddspipe_core/efficiency/payload/PayloadPoolMediator.hpp>
2628
#include <ddspipe_core/types/participant/ParticipantId.hpp>
@@ -99,7 +101,8 @@ class CommonWriter : public BaseWriter
99101
const core::types::DdsTopic& topic,
100102
const std::shared_ptr<core::PayloadPool>& payload_pool,
101103
fastdds::dds::DomainParticipant* participant,
102-
fastdds::dds::Topic* topic_entity);
104+
fastdds::dds::Topic* topic_entity,
105+
const bool repeater);
103106

104107
/////////////////////////
105108
// IWRITER METHODS
@@ -128,20 +131,30 @@ class CommonWriter : public BaseWriter
128131
// INTERNAL METHODS
129132
/////////////////////////
130133

131-
virtual
132-
fastdds::dds::PublisherQos
133-
reckon_publisher_qos_() const noexcept;
134+
DDSPIPE_PARTICIPANTS_DllAPI
135+
virtual fastdds::dds::PublisherQos reckon_publisher_qos_() const noexcept;
136+
137+
DDSPIPE_PARTICIPANTS_DllAPI
138+
virtual fastdds::dds::DataWriterQos reckon_writer_qos_() const noexcept;
134139

135-
virtual
136-
fastdds::dds::DataWriterQos
137-
reckon_writer_qos_() const noexcept;
140+
/**
141+
* @brief Auxiliary method used in \c write to fill the sample to send and write params.
142+
*
143+
* @param [out] to_send_params write params to be filled and sent.
144+
* @param [in] data data received that must be sent.
145+
*/
146+
DDSPIPE_PARTICIPANTS_DllAPI
147+
virtual utils::ReturnCode fill_to_send_data_(
148+
eprosima::fastdds::rtps::WriteParams& to_send_params,
149+
const core::types::RtpsPayloadData& data) const noexcept;
138150

139151
/////////////////////////
140152
// EXTERNAL VARIABLES
141153
/////////////////////////
142154

143155
fastdds::dds::DomainParticipant* dds_participant_;
144156
fastdds::dds::Topic* dds_topic_;
157+
bool repeater_;
145158

146159
/////////////////////////
147160
// INTERNAL VARIABLES
@@ -153,6 +166,7 @@ class CommonWriter : public BaseWriter
153166

154167
fastdds::dds::Publisher* dds_publisher_;
155168
fastdds::dds::DataWriter* writer_;
169+
std::shared_ptr<fastdds::dds::IContentFilter> data_filter_;
156170
};
157171

158172
} /* namespace dds */

ddspipe_participants/include/ddspipe_participants/writer/dds/MultiWriter.hpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ class MultiWriter : public BaseWriter
4848
* @param payload_pool Shared Payload Pool to received data and take it.
4949
* @param participant DDS Participant pointer.
5050
* @param topic_entity DDS Topic pointer.
51+
* @param repeater If this MultiWriter is a repeater or not.
5152
*
5253
* @throw \c InitializationException in case any creation has failed
5354
*/
@@ -57,7 +58,8 @@ class MultiWriter : public BaseWriter
5758
const core::types::DdsTopic& topic,
5859
const std::shared_ptr<core::PayloadPool>& payload_pool,
5960
fastdds::dds::DomainParticipant* participant,
60-
fastdds::dds::Topic* topic_entity);
61+
fastdds::dds::Topic* topic_entity,
62+
const bool repeater = false);
6163

6264
/**
6365
* @brief Destroy the MultiWriter object
@@ -99,6 +101,7 @@ class MultiWriter : public BaseWriter
99101

100102
fastdds::dds::DomainParticipant* dds_participant_;
101103
fastdds::dds::Topic* dds_topic_;
104+
bool repeater_;
102105

103106
/////////////////////////
104107
// INTERNAL VARIABLES

ddspipe_participants/include/ddspipe_participants/writer/dds/QoSSpecificWriter.hpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,10 @@ class QoSSpecificWriter : public CommonWriter
3939
* @param participant_id Router Id of the Participant that has created this QoSSpecificWriter.
4040
* @param topic Topic that this QoSSpecificWriter subscribes to.
4141
* @param payload_pool Shared Payload Pool to received data and take it.
42+
* @param specific_qos Specific QoS of the Endpoint.
4243
* @param participant DDS Participant pointer.
4344
* @param topic_entity DDS Topic pointer.
45+
* @param repeater If this QoSSpecificWriter is a repeater or not.
4446
*
4547
* @throw \c InitializationException in case any creation has failed
4648
*/
@@ -51,7 +53,8 @@ class QoSSpecificWriter : public CommonWriter
5153
const std::shared_ptr<core::PayloadPool>& payload_pool,
5254
const core::types::SpecificEndpointQoS& specific_qos,
5355
fastdds::dds::DomainParticipant* participant,
54-
fastdds::dds::Topic* topic_entity);
56+
fastdds::dds::Topic* topic_entity,
57+
const bool repeater = false);
5558

5659
protected:
5760

ddspipe_participants/include/ddspipe_participants/writer/dds/SimpleWriter.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ class SimpleWriter : public CommonWriter
4343
* @param payload_pool Shared Payload Pool to received data and take it.
4444
* @param participant DDS Participant pointer.
4545
* @param topic_entity DDS Topic pointer.
46+
* @param repeater If this SimpleWriter is a repeater or not.
4647
*
4748
* @throw \c InitializationException in case any creation has failed
4849
*/
@@ -52,7 +53,8 @@ class SimpleWriter : public CommonWriter
5253
const core::types::DdsTopic& topic,
5354
const std::shared_ptr<core::PayloadPool>& payload_pool,
5455
fastdds::dds::DomainParticipant* participant,
55-
fastdds::dds::Topic* topic_entity);
56+
fastdds::dds::Topic* topic_entity,
57+
const bool repeater = false);
5658

5759
};
5860

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// Copyright 2025 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+
#pragma once
16+
17+
#include <fastdds/rtps/common/Guid.hpp>
18+
#include <fastdds/rtps/common/WriteParams.hpp>
19+
20+
#include <ddspipe_participants/library/library_dll.h>
21+
#include <ddspipe_participants/writer/dds/filter/SelfDataFilter.hpp>
22+
23+
namespace eprosima {
24+
namespace ddspipe {
25+
namespace participants {
26+
namespace dds {
27+
28+
struct RepeaterWriteData : public fastdds::rtps::WriteParams::UserWriteData
29+
{
30+
fastdds::rtps::GuidPrefix_t last_writer_guid_prefix; ///< GUID of the writer that sent this change.
31+
};
32+
33+
/**
34+
* This filter allows to not send messages from this Writer to the Readers belonging to the source Participant.
35+
* It is used in "repeater" participants in order to propagate information to external participants
36+
* (participants not belonging to the same DDS-Router instance),
37+
* leaving out the participant from which this information was received.
38+
*/
39+
class RepeaterDataFilter : public SelfDataFilter
40+
{
41+
public:
42+
43+
DDSPIPE_PARTICIPANTS_DllAPI
44+
bool evaluate(
45+
const fastdds::rtps::SerializedPayload_t& payload,
46+
const fastdds::dds::IContentFilter::FilterSampleInfo& sample_info,
47+
const fastdds::rtps::GUID_t& reader_guid) const override;
48+
};
49+
50+
} /* namespace dds */
51+
} /* namespace participants */
52+
} /* namespace ddspipe */
53+
} /* namespace eprosima */
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Copyright 2025 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+
#pragma once
16+
17+
#include <fastdds/dds/topic/IContentFilter.hpp>
18+
19+
#include <fastdds/rtps/common/Guid.hpp>
20+
#include <fastdds/rtps/common/SerializedPayload.hpp>
21+
22+
#include <ddspipe_participants/library/library_dll.h>
23+
24+
namespace eprosima {
25+
namespace ddspipe {
26+
namespace participants {
27+
namespace dds {
28+
29+
/**
30+
* This filter allows to not send messages from this Writer to the Readers in the same Participant.
31+
*/
32+
class SelfDataFilter : public fastdds::dds::IContentFilter
33+
{
34+
public:
35+
36+
/**
37+
* @brief Whether incoming sample is relevant for this reader.
38+
*
39+
* @return true if the reader does not belong to same Participant.
40+
* @return false otherwise.
41+
*/
42+
DDSPIPE_PARTICIPANTS_DllAPI
43+
bool evaluate(
44+
const fastdds::rtps::SerializedPayload_t& payload,
45+
const fastdds::dds::IContentFilter::FilterSampleInfo& sample_info,
46+
const fastdds::rtps::GUID_t& reader_guid) const override;
47+
};
48+
49+
} /* namespace dds */
50+
} /* namespace participants */
51+
} /* namespace ddspipe */
52+
} /* namespace eprosima */

ddspipe_participants/include/ddspipe_participants/writer/rtps/CommonWriter.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ class CommonWriter : public BaseWriter, public fastdds::rtps::WriterListener
193193
core::IRoutingData& data) noexcept override;
194194

195195
/**
196-
* @brief Auxiliary method used in \c write to fill the cache change to send.
196+
* @brief Auxiliary method used in \c write to fill the cache change to send and write params.
197197
*
198198
* @param [out] to_send_change_to_fill cache change to be filled and sent.
199199
* @param [out] to_send_params write params to be filled and sent.

ddspipe_participants/src/cpp/participant/dds/CommonParticipant.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ bool CommonParticipant::is_rtps_kind() const noexcept
109109

110110
bool CommonParticipant::is_repeater() const noexcept
111111
{
112-
return false;
112+
return configuration_->is_repeater;
113113
}
114114

115115
core::types::TopicQoS CommonParticipant::topic_qos() const noexcept
@@ -147,7 +147,8 @@ std::shared_ptr<core::IWriter> CommonParticipant::create_writer(
147147
dds_topic,
148148
this->payload_pool_,
149149
dds_participant_,
150-
fastdds_topic);
150+
fastdds_topic,
151+
configuration_->is_repeater);
151152
}
152153
else
153154
{
@@ -156,7 +157,8 @@ std::shared_ptr<core::IWriter> CommonParticipant::create_writer(
156157
dds_topic,
157158
this->payload_pool_,
158159
dds_participant_,
159-
fastdds_topic);
160+
fastdds_topic,
161+
configuration_->is_repeater);
160162
writer->init();
161163

162164
return writer;

ddspipe_participants/src/cpp/writer/dds/CommonWriter.cpp

Lines changed: 59 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,20 @@
1313
// limitations under the License.
1414

1515

16-
#include <fastdds/rtps/RTPSDomain.hpp>
17-
#include <fastdds/rtps/participant/RTPSParticipant.hpp>
1816
#include <fastdds/rtps/common/CacheChange.hpp>
17+
#include <fastdds/rtps/common/WriteParams.hpp>
18+
#include <fastdds/rtps/participant/RTPSParticipant.hpp>
19+
#include <fastdds/rtps/RTPSDomain.hpp>
1920

2021
#include <cpp_utils/exception/InitializationException.hpp>
2122
#include <cpp_utils/Log.hpp>
2223
#include <cpp_utils/time/time_utils.hpp>
2324

2425
#include <ddspipe_participants/efficiency/cache_change/CacheChangePool.hpp>
25-
#include <ddspipe_participants/writer/dds/CommonWriter.hpp>
2626
#include <ddspipe_participants/types/dds/RouterCacheChange.hpp>
27+
#include <ddspipe_participants/writer/dds/CommonWriter.hpp>
28+
#include <ddspipe_participants/writer/dds/filter/RepeaterDataFilter.hpp>
29+
#include <ddspipe_participants/writer/dds/filter/SelfDataFilter.hpp>
2730

2831
namespace eprosima {
2932
namespace ddspipe {
@@ -83,19 +86,39 @@ void CommonWriter::init()
8386
utils::Formatter() << "Error creating DataWriter for Participant " <<
8487
participant_id_ << " in topic " << topic_ << ".");
8588
}
89+
90+
if (repeater_)
91+
{
92+
// Use filter writer of origin
93+
data_filter_ = std::make_shared<RepeaterDataFilter>();
94+
}
95+
else
96+
{
97+
// Use default filter
98+
data_filter_ = std::make_shared<SelfDataFilter>();
99+
}
100+
101+
if (fastdds::dds::RETCODE_OK != writer_->set_sample_prefilter(data_filter_))
102+
{
103+
throw utils::InitializationException(
104+
utils::Formatter() << "Error setting DataWriter prefilter for Participant " <<
105+
participant_id_ << " in topic " << topic_ << ".");
106+
}
86107
}
87108

88109
CommonWriter::CommonWriter(
89110
const ParticipantId& participant_id,
90111
const DdsTopic& topic,
91112
const std::shared_ptr<core::PayloadPool>& payload_pool,
92113
fastdds::dds::DomainParticipant* participant,
93-
fastdds::dds::Topic* topic_entity)
114+
fastdds::dds::Topic* topic_entity,
115+
const bool repeater)
94116
: BaseWriter(participant_id, topic.topic_qos.max_tx_rate)
95117
, dds_participant_(participant)
96118
, dds_topic_(topic_entity)
97119
, payload_pool_(new core::PayloadPoolMediator(payload_pool))
98120
, topic_(topic)
121+
, repeater_(repeater)
99122
, dds_publisher_(nullptr)
100123
, writer_(nullptr)
101124
{
@@ -110,15 +133,23 @@ utils::ReturnCode CommonWriter::write_nts_(
110133

111134
auto& rtps_data = dynamic_cast<core::types::RtpsPayloadData&>(data);
112135

113-
if (topic_.topic_qos.keyed)
114-
{
115-
// TODO check if in case of dispose it must be done something differently
116-
return payload_pool_->write(writer_, &rtps_data, rtps_data.instanceHandle);
117-
}
118-
else
136+
fastdds::rtps::WriteParams wparams;
137+
138+
if (fill_to_send_data_(wparams, rtps_data) != utils::ReturnCode::RETCODE_OK)
119139
{
120-
return payload_pool_->write(writer_, &rtps_data);
140+
EPROSIMA_LOG_ERROR(DDSPIPE_DDS_WRITER, "Error setting data to send.");
141+
return utils::ReturnCode::RETCODE_ERROR;
121142
}
143+
144+
// WARNING: At the time of this writing, there is no DataWriter API to write both with parameters and instance handle.
145+
// However, the current implementation of write without instance handle always computes its value via type support
146+
// (if it corresponds to a keyed topic), so it is equivalent to write with instance handle (and can hence use the
147+
// write with params overload to cover all cases). Future developers should be aware of this and might need to
148+
// upload this method if the DataWriter implementation changes at some point.
149+
return payload_pool_->write(writer_, &rtps_data, wparams);
150+
151+
// TODO: handle dipose case -> DataWriter::write will always send ALIVE changes, so this case must be handled
152+
// with additional logic (e.g. by using unregister_instance instead of write).
122153
}
123154

124155
fastdds::dds::PublisherQos CommonWriter::reckon_publisher_qos_() const noexcept
@@ -172,6 +203,23 @@ fastdds::dds::DataWriterQos CommonWriter::reckon_writer_qos_() const noexcept
172203
return qos;
173204
}
174205

206+
utils::ReturnCode CommonWriter::fill_to_send_data_(
207+
fastdds::rtps::WriteParams& to_send_params,
208+
const RtpsPayloadData& data) const noexcept
209+
{
210+
if (repeater_)
211+
{
212+
auto write_data = std::make_shared<RepeaterWriteData>();
213+
write_data->last_writer_guid_prefix = data.source_guid.guidPrefix;
214+
to_send_params.user_write_data(write_data);
215+
}
216+
217+
// Set source time stamp to be the original one
218+
to_send_params.source_timestamp(data.source_timestamp);
219+
220+
return utils::ReturnCode::RETCODE_OK;
221+
}
222+
175223
} /* namespace dds */
176224
} /* namespace participants */
177225
} /* namespace ddspipe */

0 commit comments

Comments
 (0)