diff --git a/code/DDSCodeTester.cpp b/code/DDSCodeTester.cpp index 27b7206cc..b56cf9cfd 100644 --- a/code/DDSCodeTester.cpp +++ b/code/DDSCodeTester.cpp @@ -3285,6 +3285,96 @@ void dds_dataWriter_examples() //! } } + + { + //DDS_DATAWRITER_SAMPLE_PREFILTER + struct CustomUserWriteData : public eprosima::fastdds::rtps::WriteParams::UserWriteData + { + CustomUserWriteData( + const eprosima::fastdds::rtps::GuidPrefix_t& prefix) + : filtered_out_prefix(prefix) + { + } + + eprosima::fastdds::rtps::GuidPrefix_t filtered_out_prefix; + }; + + struct CustomPreFilter : public eprosima::fastdds::dds::IContentFilter + { + // Custom evaluation + bool evaluate( + const SerializedPayload& payload, + const FilterSampleInfo& filter_sample_info, + const eprosima::fastdds::rtps::GUID_t& reader_guid) const override + { + static_cast(payload); + static_cast(filter_sample_info); + + bool sample_should_be_sent = true; + + auto custom_write_data = + std::static_pointer_cast( + filter_sample_info.user_write_data); + + // If the reader is the one to filter out, do not send the sample + if (custom_write_data->filtered_out_prefix == reader_guid.guidPrefix) + { + sample_should_be_sent = false; + } + return sample_should_be_sent; + } + + }; + + // Create a DataWriter + DataWriter* data_writer = + publisher->create_datawriter(topic, DATAWRITER_QOS_DEFAULT); + if (nullptr == data_writer) + { + // Error + return; + } + + // Set a prefilter on the filtered reader + eprosima::fastdds::dds::ReturnCode_t ret = data_writer->set_sample_prefilter( + std::make_shared()); + + if (ret != eprosima::fastdds::dds::RETCODE_OK) + { + // Error + return; + } + + // Create a custom user write data + eprosima::fastdds::rtps::GuidPrefix_t filtered_out_prefix; + filtered_out_prefix.value[0] = 0x01; // Example prefix to filter out + filtered_out_prefix.value[1] = eprosima::fastdds::rtps::octet(0x73); + filtered_out_prefix.value[2] = eprosima::fastdds::rtps::octet(0x71); + filtered_out_prefix.value[3] = eprosima::fastdds::rtps::octet(0x85); + filtered_out_prefix.value[4] = eprosima::fastdds::rtps::octet(0x69); + filtered_out_prefix.value[5] = eprosima::fastdds::rtps::octet(0x76); + filtered_out_prefix.value[6] = eprosima::fastdds::rtps::octet(0x95); + filtered_out_prefix.value[7] = eprosima::fastdds::rtps::octet(0x66); + filtered_out_prefix.value[8] = eprosima::fastdds::rtps::octet(0x65); + filtered_out_prefix.value[9] = eprosima::fastdds::rtps::octet(0x82); + filtered_out_prefix.value[10] = eprosima::fastdds::rtps::octet(0x82); + filtered_out_prefix.value[11] = eprosima::fastdds::rtps::octet(0x79); + + std::shared_ptr custom_write_data = + std::make_shared(filtered_out_prefix); + + // Set the custom user write data + eprosima::fastdds::rtps::WriteParams write_params; + write_params.user_write_data(custom_write_data); + + HelloWorld sample; //Auto-generated container class for topic data from Fast DDS-Gen + sample.msg("Hello there!"); // Add contents to the message + + // Write a sample with the custom user write data + data_writer->write(&sample, write_params); + + //!-- + } } //DDS_SUBSCRIBER_LISTENER_SPECIALIZATION diff --git a/docs/03-exports/aliases-api.include b/docs/03-exports/aliases-api.include index d77292caa..10e690236 100644 --- a/docs/03-exports/aliases-api.include +++ b/docs/03-exports/aliases-api.include @@ -88,6 +88,7 @@ .. |DataWriter::register_instance_w_timestamp| replace:: :cpp:func:`DataWriter::register_instance_w_timestamp()` .. |DataWriter::unregister_instance_w_timestamp| replace:: :cpp:func:`DataWriter::unregister_instance_w_timestamp()` .. |DataWriter::dispose_w_timestamp| replace:: :cpp:func:`DataWriter::dispose_w_timestamp()` +.. |DataWriter::set_sample_prefilter| replace:: :cpp:func:`DataWriter::set_sample_prefilter()` .. |DataWriterListener-api| replace:: :cpp:class:`DataWriterListener ` @@ -238,6 +239,8 @@ .. |IContentFilter-api| replace:: :cpp:class:`IContentFilter` .. |IContentFilter::evaluate-api| replace:: :cpp:func:`evaluate()` +.. |FilteredSampleInfo-api| replace:: :cpp:class:`FilteredSampleInfo` +.. |FilteredSampleInfo::user_write_data-api| replace:: :cpp:member:`user_write_data` .. |IContentFilterFactory-api| replace:: :cpp:class:`IContentFilterFactory` .. |IContentFilterFactory::create_content_filter-api| replace:: :cpp:func:`create_content_filter()` .. |IContentFilterFactory::delete_content_filter-api| replace:: :cpp:func:`delete_content_filter()` @@ -1122,6 +1125,7 @@ .. |WriteParams-api| replace:: :cpp:class:`WriteParams ` .. |WriteParams-sample_identity-api| replace:: :cpp:func:`sample_identity() ` .. |WriteParams-related_sample_identity-api| replace:: :cpp:func:`related_sample_identity() ` +.. |WriteParams-user_write_data-api| replace:: :cpp:func:`user_write_data() ` .. |ThreadSettings::scheduling_policy-api| replace:: :cpp:member:`scheduling_policy` .. |ThreadSettings::priority-api| replace:: :cpp:member:`priority` diff --git a/docs/fastdds/dds_layer/publisher/dataWriter/publishingData.rst b/docs/fastdds/dds_layer/publisher/dataWriter/publishingData.rst index ca84a806c..7e290a310 100644 --- a/docs/fastdds/dds_layer/publisher/dataWriter/publishingData.rst +++ b/docs/fastdds/dds_layer/publisher/dataWriter/publishingData.rst @@ -83,3 +83,35 @@ Otherwise the DataWriter may run out of samples. :start-after: //DDS_DATAWRITER_LOAN_SAMPLES :end-before: //! :dedent: 8 + +.. _dds_layer_publisher_prefiltering: + +Prefiltering out DataReaders +---------------------------- + +The user can use an overload of the |DataWriter::write-api| method that allows providing a |WriteParams-api| structure. +One of the members of this latter structure is the |WriteParams-user_write_data-api| in which the user +can store extra information to be used by the prefiltering mechanism. + +By implementing the |IContentFilter-api| and passing it to the DataWriter with |DataWriter::set_sample_prefilter|, +user can prevent the DataWriter from sending samples to the matched DataReaders based on both: +the content of the sample (|SerializedPayload_t-api|) and/or the |WriteParams-user_write_data-api| +within |FilteredSampleInfo::user_write_data-api|. +If the return value of |IContentFilter::evaluate-api| is ``false``, the sample will not be sent to the DataReader +identified by its |Guid_t-api| in the method's input argument. +It is strongly recommended that the |IContentFilter::evaluate-api| implementation neither performs any blocking +operation nor uses the DataWriter, as this may lead to deadlocks or undesired behavior. + +.. warning:: + + Prefiltering is currently incompatible with :ref:`datasharingqospolicy`. + Hence, ensure that the |DataSharingQosPolicy::kind-api| is set to ``OFF`` or + if ``AUTO`` is used, :ref:`constraints` are not met. + +Next is an example of how to use the prefiltering mechanism: + +.. literalinclude:: /../code/DDSCodeTester.cpp + :language: c++ + :start-after: //DDS_DATAWRITER_SAMPLE_PREFILTER + :end-before: //! + :dedent: 8 diff --git a/docs/spelling_wordlist.txt b/docs/spelling_wordlist.txt index 2a67dd278..d3bba1426 100644 --- a/docs/spelling_wordlist.txt +++ b/docs/spelling_wordlist.txt @@ -239,6 +239,10 @@ preallocated preallocates preallocation preconfigure +prefilter +Prefilter +prefiltering +Prefiltering prepended preprocessor programmatically