From 36ce3143141bb4e480500e046ad96620cc4b7093 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Gonz=C3=A1lez=20Moreno?= Date: Wed, 23 Mar 2022 10:50:51 +0100 Subject: [PATCH 01/17] Refs #13791. Add DefaultSQLFilter example MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ricardo González Moreno --- examples/C++/DDS/CMakeLists.txt | 1 + .../C++/DDS/ContentFilterTopic/CMakeLists.txt | 60 +++++ .../DefaultSQLFilterPublisher.cpp | 185 +++++++++++++ .../DefaultSQLFilterPublisher.hpp | 96 +++++++ .../DefaultSQLFilterSubscriber.cpp | 162 ++++++++++++ .../DefaultSQLFilterSubscriber.hpp | 86 ++++++ .../DefaultSQLFilter_main.cpp | 86 ++++++ .../C++/DDS/ContentFilterTopic/HelloWorld.cxx | 239 +++++++++++++++++ .../C++/DDS/ContentFilterTopic/HelloWorld.h | 232 ++++++++++++++++ .../C++/DDS/ContentFilterTopic/HelloWorld.idl | 5 + .../HelloWorldPubSubTypes.cxx | 170 ++++++++++++ .../HelloWorldPubSubTypes.h | 101 +++++++ .../HelloWorldTypeObject.cxx | 248 ++++++++++++++++++ .../ContentFilterTopic/HelloWorldTypeObject.h | 63 +++++ 14 files changed, 1734 insertions(+) create mode 100644 examples/C++/DDS/ContentFilterTopic/CMakeLists.txt create mode 100644 examples/C++/DDS/ContentFilterTopic/DefaultSQLFilterPublisher.cpp create mode 100644 examples/C++/DDS/ContentFilterTopic/DefaultSQLFilterPublisher.hpp create mode 100644 examples/C++/DDS/ContentFilterTopic/DefaultSQLFilterSubscriber.cpp create mode 100644 examples/C++/DDS/ContentFilterTopic/DefaultSQLFilterSubscriber.hpp create mode 100644 examples/C++/DDS/ContentFilterTopic/DefaultSQLFilter_main.cpp create mode 100644 examples/C++/DDS/ContentFilterTopic/HelloWorld.cxx create mode 100644 examples/C++/DDS/ContentFilterTopic/HelloWorld.h create mode 100644 examples/C++/DDS/ContentFilterTopic/HelloWorld.idl create mode 100644 examples/C++/DDS/ContentFilterTopic/HelloWorldPubSubTypes.cxx create mode 100644 examples/C++/DDS/ContentFilterTopic/HelloWorldPubSubTypes.h create mode 100644 examples/C++/DDS/ContentFilterTopic/HelloWorldTypeObject.cxx create mode 100644 examples/C++/DDS/ContentFilterTopic/HelloWorldTypeObject.h diff --git a/examples/C++/DDS/CMakeLists.txt b/examples/C++/DDS/CMakeLists.txt index 53ccd3c48eb..7998ad9886c 100644 --- a/examples/C++/DDS/CMakeLists.txt +++ b/examples/C++/DDS/CMakeLists.txt @@ -18,6 +18,7 @@ add_subdirectory(BasicConfigurationExample) add_subdirectory(Benchmark) add_subdirectory(ClientServerTest) add_subdirectory(Configurability) +add_subdirectory(ContentFilterTopic) add_subdirectory(CustomListenerExample) add_subdirectory(DeadlineQoSExample) add_subdirectory(DisablePositiveACKs) diff --git a/examples/C++/DDS/ContentFilterTopic/CMakeLists.txt b/examples/C++/DDS/ContentFilterTopic/CMakeLists.txt new file mode 100644 index 00000000000..aa50cb19365 --- /dev/null +++ b/examples/C++/DDS/ContentFilterTopic/CMakeLists.txt @@ -0,0 +1,60 @@ +# Copyright 2022 Proyectos y Sistemas de Mantenimiento SL (eProsima). +# +# 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. + +cmake_minimum_required(VERSION 3.16.3) + +project("ContentFilterTopic" VERSION 1 LANGUAGES CXX) + +# Find requirements +if(NOT fastcdr_FOUND) + find_package(fastcdr REQUIRED) +endif() + +if(NOT fastrtps_FOUND) + find_package(fastrtps REQUIRED) +endif() + +message(STATUS "Configuring ContentFilterTopic examples...") + +set(CFT_COMMON_SOURCES + HelloWorld.cxx + HelloWorldPubSubTypes.cxx + HelloWorldTypeObject.cxx + ) + +set(CFT_DSF_SOURCES + DefaultSQLFilterPublisher.cpp + DefaultSQLFilterSubscriber.cpp + DefaultSQLFilter_main.cpp) + + +add_executable(DefaultSQLFilter ${CFT_COMMON_SOURCES} ${CFT_DSF_SOURCES}) +target_compile_definitions(DefaultSQLFilter PRIVATE + $<$>,$>:__DEBUG> + $<$:__INTERNALDEBUG> # Internal debug activated. +) +target_compile_features(DefaultSQLFilter PRIVATE cxx_std_11) +target_link_libraries(DefaultSQLFilter fastrtps fastcdr) +install(TARGETS DefaultSQLFilter + RUNTIME DESTINATION examples/C++/DDS/ContentFilterTopic/${BIN_INSTALL_DIR}) + +#add_executable(CustomFilter ${CFT_COMMON_SOURCES}) +#target_compile_definitions(CustomFilter PRIVATE +# $<$>,$>:__DEBUG> +# $<$:__INTERNALDEBUG> # Internal debug activated. +#) +#target_compile_features(CustomFilter PRIVATE cxx_std_11) +#target_link_libraries(CustomFilter fastrtps fastcdr) +#install(TARGETS CustomFilter +# RUNTIME DESTINATION examples/C++/DDS/ContentFilterTopic/${BIN_INSTALL_DIR}) diff --git a/examples/C++/DDS/ContentFilterTopic/DefaultSQLFilterPublisher.cpp b/examples/C++/DDS/ContentFilterTopic/DefaultSQLFilterPublisher.cpp new file mode 100644 index 00000000000..9f05972c1ba --- /dev/null +++ b/examples/C++/DDS/ContentFilterTopic/DefaultSQLFilterPublisher.cpp @@ -0,0 +1,185 @@ +// Copyright 2022 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// 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. + +/** + * @file DefaultSQLFilterPublisher.cpp + * + */ + +#include "DefaultSQLFilterPublisher.hpp" +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace eprosima::fastdds::dds; + +DefaultSQLFilterPublisher::DefaultSQLFilterPublisher() + : participant_(nullptr) + , publisher_(nullptr) + , topic_(nullptr) + , writer_(nullptr) + , type_(new HelloWorldPubSubType()) +{ +} + +bool DefaultSQLFilterPublisher::init() +{ + hello_.index(0); + hello_.message("HelloWorld"); + DomainParticipantQos pqos; + pqos.name("Participant_pub"); + participant_ = DomainParticipantFactory::get_instance()->create_participant(0, pqos); + + if (participant_ == nullptr) + { + return false; + } + + //REGISTER THE TYPE + type_.register_type(participant_); + + //CREATE THE PUBLISHER + publisher_ = participant_->create_publisher(PUBLISHER_QOS_DEFAULT, nullptr); + + if (publisher_ == nullptr) + { + return false; + } + + topic_ = participant_->create_topic("HelloWorldTopic", "HelloWorld", TOPIC_QOS_DEFAULT); + + if (topic_ == nullptr) + { + return false; + } + + // CREATE THE WRITER + writer_ = publisher_->create_datawriter(topic_, DATAWRITER_QOS_DEFAULT, &listener_); + + if (writer_ == nullptr) + { + return false; + } + return true; +} + +DefaultSQLFilterPublisher::~DefaultSQLFilterPublisher() +{ + if (writer_ != nullptr) + { + publisher_->delete_datawriter(writer_); + } + if (publisher_ != nullptr) + { + participant_->delete_publisher(publisher_); + } + if (topic_ != nullptr) + { + participant_->delete_topic(topic_); + } + DomainParticipantFactory::get_instance()->delete_participant(participant_); +} + +void DefaultSQLFilterPublisher::PubListener::on_publication_matched( + eprosima::fastdds::dds::DataWriter*, + const eprosima::fastdds::dds::PublicationMatchedStatus& info) +{ + if (info.current_count_change == 1) + { + matched_ = info.total_count; + firstConnected_ = true; + std::cout << "Publisher matched." << std::endl; + } + else if (info.current_count_change == -1) + { + matched_ = info.total_count; + std::cout << "Publisher unmatched." << std::endl; + } + else + { + std::cout << info.current_count_change + << " is not a valid value for PublicationMatchedStatus current count change" << std::endl; + } +} + +void DefaultSQLFilterPublisher::runThread( + uint32_t samples, + uint32_t sleep) +{ + if (samples == 0) + { + while (!stop_) + { + if (publish(false)) + { + std::cout << "Message: " << hello_.message() << " with index: " << hello_.index() + << " SENT" << std::endl; + } + std::this_thread::sleep_for(std::chrono::milliseconds(sleep)); + } + } + else + { + for (uint32_t i = 0; i < samples; ++i) + { + if (!publish()) + { + --i; + } + else + { + std::cout << "Message: " << hello_.message() << " with index: " << hello_.index() + << " SENT" << std::endl; + } + std::this_thread::sleep_for(std::chrono::milliseconds(sleep)); + } + } +} + +void DefaultSQLFilterPublisher::run( + uint32_t samples, + uint32_t sleep) +{ + stop_ = false; + std::thread thread(&DefaultSQLFilterPublisher::runThread, this, samples, sleep); + if (samples == 0) + { + std::cout << "Publisher running. Please press enter to stop the Publisher at any time." << std::endl; + std::cin.ignore(); + stop_ = true; + } + else + { + std::cout << "Publisher running " << samples << " samples." << std::endl; + } + thread.join(); +} + +bool DefaultSQLFilterPublisher::publish( + bool waitForListener) +{ + if (listener_.firstConnected_ || !waitForListener || listener_.matched_ > 0) + { + hello_.index(hello_.index() + 1); + writer_->write(&hello_); + return true; + } + return false; +} diff --git a/examples/C++/DDS/ContentFilterTopic/DefaultSQLFilterPublisher.hpp b/examples/C++/DDS/ContentFilterTopic/DefaultSQLFilterPublisher.hpp new file mode 100644 index 00000000000..ca75a26372b --- /dev/null +++ b/examples/C++/DDS/ContentFilterTopic/DefaultSQLFilterPublisher.hpp @@ -0,0 +1,96 @@ +// Copyright 2022 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// 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. + +/** + * @file DefaultSQFilterPublisher.hpp + * + */ + +#ifndef _DEFAULTSQLFILTERPUBLISHER_H_ +#define _DEFAULTSQLFILTERPUBLISHER_H_ + +#include "HelloWorldPubSubTypes.h" + +#include +#include +#include + +class DefaultSQLFilterPublisher +{ +public: + + DefaultSQLFilterPublisher(); + + virtual ~DefaultSQLFilterPublisher(); + + //!Initialize + bool init(); + + //!Publish a sample + bool publish( + bool waitForListener = true); + + //!Run for number samples + void run( + uint32_t number, + uint32_t sleep); + +private: + + HelloWorld hello_; + + eprosima::fastdds::dds::DomainParticipant* participant_; + + eprosima::fastdds::dds::Publisher* publisher_; + + eprosima::fastdds::dds::Topic* topic_; + + eprosima::fastdds::dds::DataWriter* writer_; + + bool stop_; + + class PubListener : public eprosima::fastdds::dds::DataWriterListener + { + public: + + PubListener() + : matched_(0) + , firstConnected_(false) + { + } + + ~PubListener() override + { + } + + void on_publication_matched( + eprosima::fastdds::dds::DataWriter* writer, + const eprosima::fastdds::dds::PublicationMatchedStatus& info) override; + + int matched_; + + bool firstConnected_; + } + listener_; + + void runThread( + uint32_t number, + uint32_t sleep); + + eprosima::fastdds::dds::TypeSupport type_; +}; + + + +#endif // _DEFAULTSQLFILTERPUBLISHER_H_ diff --git a/examples/C++/DDS/ContentFilterTopic/DefaultSQLFilterSubscriber.cpp b/examples/C++/DDS/ContentFilterTopic/DefaultSQLFilterSubscriber.cpp new file mode 100644 index 00000000000..9a2682572e0 --- /dev/null +++ b/examples/C++/DDS/ContentFilterTopic/DefaultSQLFilterSubscriber.cpp @@ -0,0 +1,162 @@ +// Copyright 2022 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// 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. + +/** + * @file DefaultSQLFilterSubscriber.cpp + * + */ + +#include "DefaultSQLFilterSubscriber.hpp" +#include +#include +#include +#include +#include +#include +#include + +using namespace eprosima::fastdds::dds; + +bool DefaultSQLFilterSubscriber::init() +{ + DomainParticipantQos pqos; + pqos.name("Participant_sub"); + participant_ = DomainParticipantFactory::get_instance()->create_participant(0, pqos); + + if (participant_ == nullptr) + { + return false; + } + + //Register the type + type_.register_type(participant_); + + //CREATE THE SUBSCRIBER + subscriber_ = participant_->create_subscriber(SUBSCRIBER_QOS_DEFAULT, nullptr); + + if (subscriber_ == nullptr) + { + return false; + } + + //Create the topic + topic_ = participant_->create_topic( + "HelloWorldTopic", + "HelloWorld", + TOPIC_QOS_DEFAULT); + + if (topic_ == nullptr) + { + return false; + } + + // Create a ContentFilteredTopic using an expression with no parameters + std::string expression = "index < %0 or index > %1"; + std::vector parameters; + parameters.push_back("3"); + parameters.push_back("5"); + filter_topic_ = + participant_->create_contentfilteredtopic("HelloWorldFilteredTopic1", topic_, expression, parameters); + + if (nullptr == filter_topic_) + { + // Error + return false; + } + + // CREATE THE READER + DataReaderQos rqos = DATAREADER_QOS_DEFAULT; + rqos.reliability().kind = RELIABLE_RELIABILITY_QOS; + reader_ = subscriber_->create_datareader(filter_topic_, rqos, &listener_); + + if (reader_ == nullptr) + { + return false; + } + + return true; +} + +DefaultSQLFilterSubscriber::~DefaultSQLFilterSubscriber() +{ + if (reader_ != nullptr) + { + subscriber_->delete_datareader(reader_); + } + if (nullptr != filter_topic_) + { + participant_->delete_contentfilteredtopic(filter_topic_); + } + if (topic_ != nullptr) + { + participant_->delete_topic(topic_); + } + if (subscriber_ != nullptr) + { + participant_->delete_subscriber(subscriber_); + } + DomainParticipantFactory::get_instance()->delete_participant(participant_); +} + +void DefaultSQLFilterSubscriber::SubListener::on_subscription_matched( + DataReader*, + const SubscriptionMatchedStatus& info) +{ + if (info.current_count_change == 1) + { + matched_ = info.total_count; + std::cout << "Subscriber matched." << std::endl; + } + else if (info.current_count_change == -1) + { + matched_ = info.total_count; + std::cout << "Subscriber unmatched." << std::endl; + } + else + { + std::cout << info.current_count_change + << " is not a valid value for SubscriptionMatchedStatus current count change" << std::endl; + } +} + +void DefaultSQLFilterSubscriber::SubListener::on_data_available( + DataReader* reader) +{ + SampleInfo info; + if (reader->take_next_sample(&hello_, &info) == ReturnCode_t::RETCODE_OK) + { + if (info.instance_state == ALIVE_INSTANCE_STATE) + { + samples_++; + // Print your structure data here. + std::cout << "Message " << hello_.message() << " " << hello_.index() << " RECEIVED" << std::endl; + } + } +} + +void DefaultSQLFilterSubscriber::run() +{ + std::cout << "Subscriber running. Please press enter to stop the Subscriber" << std::endl; + std::cin.ignore(); +} + +void DefaultSQLFilterSubscriber::run( + uint32_t number) +{ + std::cout << "Subscriber running until " << number << "samples have been received" << std::endl; + while (number > listener_.samples_) + { + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + } +} diff --git a/examples/C++/DDS/ContentFilterTopic/DefaultSQLFilterSubscriber.hpp b/examples/C++/DDS/ContentFilterTopic/DefaultSQLFilterSubscriber.hpp new file mode 100644 index 00000000000..ddff178fb6f --- /dev/null +++ b/examples/C++/DDS/ContentFilterTopic/DefaultSQLFilterSubscriber.hpp @@ -0,0 +1,86 @@ +// Copyright 2021 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// 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. + +/** + * @file DefaultSQLFilterSubscriber.hpp + * + */ + +#ifndef _DEFAULTSQLFILTERSUBSCRIBER_HPP_ +#define _DEFAULTSQLFILTERSUBSCRIBER_HPP_ + +#include "HelloWorldPubSubTypes.h" + +#include +#include +#include +#include + +class DefaultSQLFilterSubscriber +{ +public: + + DefaultSQLFilterSubscriber() = default; + + virtual ~DefaultSQLFilterSubscriber(); + + //!Initialize the subscriber + bool init(); + + //!RUN the subscriber + void run(); + + //!Run the subscriber until number samples have been received. + void run( + uint32_t number); + +private: + + eprosima::fastdds::dds::DomainParticipant* participant_ = nullptr; + + eprosima::fastdds::dds::Subscriber* subscriber_ = nullptr; + + eprosima::fastdds::dds::Topic* topic_ = nullptr; + + eprosima::fastdds::dds::ContentFilteredTopic* filter_topic_ = nullptr; + + eprosima::fastdds::dds::DataReader* reader_ = nullptr; + + eprosima::fastdds::dds::TypeSupport type_ = eprosima::fastdds::dds::TypeSupport(new HelloWorldPubSubType()); + + class SubListener : public eprosima::fastdds::dds::DataReaderListener + { + public: + + ~SubListener() override + { + } + + void on_data_available( + eprosima::fastdds::dds::DataReader* reader) override; + + void on_subscription_matched( + eprosima::fastdds::dds::DataReader* reader, + const eprosima::fastdds::dds::SubscriptionMatchedStatus& info) override; + + HelloWorld hello_; + + int matched_ = 0; + + uint32_t samples_ = 0; + } + listener_; +}; + +#endif // _DEFAULTSQLFILTERSUBSCRIBER_HPP_ diff --git a/examples/C++/DDS/ContentFilterTopic/DefaultSQLFilter_main.cpp b/examples/C++/DDS/ContentFilterTopic/DefaultSQLFilter_main.cpp new file mode 100644 index 00000000000..8a23a239a51 --- /dev/null +++ b/examples/C++/DDS/ContentFilterTopic/DefaultSQLFilter_main.cpp @@ -0,0 +1,86 @@ +// Copyright 2022 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// 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. + +/** + * @file HelloWorld_main.cpp + * + */ + +#include "DefaultSQLFilterPublisher.hpp" +#include "DefaultSQLFilterSubscriber.hpp" + +#include + +#include + +using eprosima::fastdds::dds::Log; + +int main( + int argc, + char** argv) +{ + std::cout << "Starting " << std::endl; + int type = 1; + int count = 10; + int sleep = 100; + if (argc > 1) + { + if (strcmp(argv[1], "publisher") == 0) + { + type = 1; + if (argc >= 3) + { + count = atoi(argv[2]); + if (argc == 4) + { + sleep = atoi(argv[3]); + } + } + } + else if (strcmp(argv[1], "subscriber") == 0) + { + type = 2; + } + } + else + { + std::cout << "publisher OR subscriber argument needed" << std::endl; + Log::Reset(); + return 0; + } + + switch (type) + { + case 1: + { + DefaultSQLFilterPublisher mypub; + if (mypub.init()) + { + mypub.run(static_cast(count), static_cast(sleep)); + } + break; + } + case 2: + { + DefaultSQLFilterSubscriber mysub; + if (mysub.init()) + { + mysub.run(); + } + break; + } + } + Log::Reset(); + return 0; +} diff --git a/examples/C++/DDS/ContentFilterTopic/HelloWorld.cxx b/examples/C++/DDS/ContentFilterTopic/HelloWorld.cxx new file mode 100644 index 00000000000..7cdda355f4f --- /dev/null +++ b/examples/C++/DDS/ContentFilterTopic/HelloWorld.cxx @@ -0,0 +1,239 @@ +// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// 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. + +/*! + * @file HelloWorld.cpp + * This source file contains the definition of the described types in the IDL file. + * + * This file was generated by the tool gen. + */ + +#ifdef _WIN32 +// Remove linker warning LNK4221 on Visual Studio +namespace { +char dummy; +} // namespace +#endif // _WIN32 + +#include "HelloWorld.h" +#include "HelloWorldTypeObject.h" +#include + +#include +using namespace eprosima::fastcdr::exception; + +#include + +HelloWorld::HelloWorld() +{ + // m_index com.eprosima.idl.parser.typecode.PrimitiveTypeCode@1f36e637 + m_index = 0; + // m_message com.eprosima.idl.parser.typecode.StringTypeCode@578486a3 + m_message =""; + + // Just to register all known types + registerHelloWorldTypes(); +} + +HelloWorld::~HelloWorld() +{ + + +} + +HelloWorld::HelloWorld( + const HelloWorld& x) +{ + m_index = x.m_index; + m_message = x.m_message; +} + +HelloWorld::HelloWorld( + HelloWorld&& x) +{ + m_index = x.m_index; + m_message = std::move(x.m_message); +} + +HelloWorld& HelloWorld::operator =( + const HelloWorld& x) +{ + + m_index = x.m_index; + m_message = x.m_message; + + return *this; +} + +HelloWorld& HelloWorld::operator =( + HelloWorld&& x) +{ + + m_index = x.m_index; + m_message = std::move(x.m_message); + + return *this; +} + +bool HelloWorld::operator ==( + const HelloWorld& x) const +{ + + return (m_index == x.m_index && m_message == x.m_message); +} + +bool HelloWorld::operator !=( + const HelloWorld& x) const +{ + return !(*this == x); +} + +size_t HelloWorld::getMaxCdrSerializedSize( + size_t current_alignment) +{ + size_t initial_alignment = current_alignment; + + + current_alignment += 4 + eprosima::fastcdr::Cdr::alignment(current_alignment, 4); + + + current_alignment += 4 + eprosima::fastcdr::Cdr::alignment(current_alignment, 4) + 255 + 1; + + + return current_alignment - initial_alignment; +} + +size_t HelloWorld::getCdrSerializedSize( + const HelloWorld& data, + size_t current_alignment) +{ + (void)data; + size_t initial_alignment = current_alignment; + + + current_alignment += 4 + eprosima::fastcdr::Cdr::alignment(current_alignment, 4); + + + current_alignment += 4 + eprosima::fastcdr::Cdr::alignment(current_alignment, 4) + data.message().size() + 1; + + + return current_alignment - initial_alignment; +} + +void HelloWorld::serialize( + eprosima::fastcdr::Cdr& scdr) const +{ + + scdr << m_index; + scdr << m_message; + +} + +void HelloWorld::deserialize( + eprosima::fastcdr::Cdr& dcdr) +{ + + dcdr >> m_index; + dcdr >> m_message; +} + +/*! + * @brief This function sets a value in member index + * @param _index New value for member index + */ +void HelloWorld::index( + uint32_t _index) +{ + m_index = _index; +} + +/*! + * @brief This function returns the value of member index + * @return Value of member index + */ +uint32_t HelloWorld::index() const +{ + return m_index; +} + +/*! + * @brief This function returns a reference to member index + * @return Reference to member index + */ +uint32_t& HelloWorld::index() +{ + return m_index; +} + +/*! + * @brief This function copies the value in member message + * @param _message New value to be copied in member message + */ +void HelloWorld::message( + const std::string& _message) +{ + m_message = _message; +} + +/*! + * @brief This function moves the value in member message + * @param _message New value to be moved in member message + */ +void HelloWorld::message( + std::string&& _message) +{ + m_message = std::move(_message); +} + +/*! + * @brief This function returns a constant reference to member message + * @return Constant reference to member message + */ +const std::string& HelloWorld::message() const +{ + return m_message; +} + +/*! + * @brief This function returns a reference to member message + * @return Reference to member message + */ +std::string& HelloWorld::message() +{ + return m_message; +} + +size_t HelloWorld::getKeyMaxCdrSerializedSize( + size_t current_alignment) +{ + size_t current_align = current_alignment; + + + + + + return current_align; +} + +bool HelloWorld::isKeyDefined() +{ + return false; +} + +void HelloWorld::serializeKey( + eprosima::fastcdr::Cdr& scdr) const +{ + (void) scdr; + +} diff --git a/examples/C++/DDS/ContentFilterTopic/HelloWorld.h b/examples/C++/DDS/ContentFilterTopic/HelloWorld.h new file mode 100644 index 00000000000..ca96c339a28 --- /dev/null +++ b/examples/C++/DDS/ContentFilterTopic/HelloWorld.h @@ -0,0 +1,232 @@ +// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// 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. + +/*! + * @file HelloWorld.h + * This header file contains the declaration of the described types in the IDL file. + * + * This file was generated by the tool gen. + */ + +#ifndef _FAST_DDS_GENERATED_HELLOWORLD_H_ +#define _FAST_DDS_GENERATED_HELLOWORLD_H_ + + +#include +#include +#include +#include +#include +#include + +#if defined(_WIN32) +#if defined(EPROSIMA_USER_DLL_EXPORT) +#define eProsima_user_DllExport __declspec( dllexport ) +#else +#define eProsima_user_DllExport +#endif // EPROSIMA_USER_DLL_EXPORT +#else +#define eProsima_user_DllExport +#endif // _WIN32 + +#if defined(_WIN32) +#if defined(EPROSIMA_USER_DLL_EXPORT) +#if defined(HelloWorld_SOURCE) +#define HelloWorld_DllAPI __declspec( dllexport ) +#else +#define HelloWorld_DllAPI __declspec( dllimport ) +#endif // HelloWorld_SOURCE +#else +#define HelloWorld_DllAPI +#endif // EPROSIMA_USER_DLL_EXPORT +#else +#define HelloWorld_DllAPI +#endif // _WIN32 + +namespace eprosima { +namespace fastcdr { +class Cdr; +} // namespace fastcdr +} // namespace eprosima + + +/*! + * @brief This class represents the structure HelloWorld defined by the user in the IDL file. + * @ingroup HELLOWORLD + */ +class HelloWorld +{ +public: + + /*! + * @brief Default constructor. + */ + eProsima_user_DllExport HelloWorld(); + + /*! + * @brief Default destructor. + */ + eProsima_user_DllExport ~HelloWorld(); + + /*! + * @brief Copy constructor. + * @param x Reference to the object HelloWorld that will be copied. + */ + eProsima_user_DllExport HelloWorld( + const HelloWorld& x); + + /*! + * @brief Move constructor. + * @param x Reference to the object HelloWorld that will be copied. + */ + eProsima_user_DllExport HelloWorld( + HelloWorld&& x); + + /*! + * @brief Copy assignment. + * @param x Reference to the object HelloWorld that will be copied. + */ + eProsima_user_DllExport HelloWorld& operator =( + const HelloWorld& x); + + /*! + * @brief Move assignment. + * @param x Reference to the object HelloWorld that will be copied. + */ + eProsima_user_DllExport HelloWorld& operator =( + HelloWorld&& x); + + /*! + * @brief Comparison operator. + * @param x HelloWorld object to compare. + */ + eProsima_user_DllExport bool operator ==( + const HelloWorld& x) const; + + /*! + * @brief Comparison operator. + * @param x HelloWorld object to compare. + */ + eProsima_user_DllExport bool operator !=( + const HelloWorld& x) const; + + /*! + * @brief This function sets a value in member index + * @param _index New value for member index + */ + eProsima_user_DllExport void index( + uint32_t _index); + + /*! + * @brief This function returns the value of member index + * @return Value of member index + */ + eProsima_user_DllExport uint32_t index() const; + + /*! + * @brief This function returns a reference to member index + * @return Reference to member index + */ + eProsima_user_DllExport uint32_t& index(); + + /*! + * @brief This function copies the value in member message + * @param _message New value to be copied in member message + */ + eProsima_user_DllExport void message( + const std::string& _message); + + /*! + * @brief This function moves the value in member message + * @param _message New value to be moved in member message + */ + eProsima_user_DllExport void message( + std::string&& _message); + + /*! + * @brief This function returns a constant reference to member message + * @return Constant reference to member message + */ + eProsima_user_DllExport const std::string& message() const; + + /*! + * @brief This function returns a reference to member message + * @return Reference to member message + */ + eProsima_user_DllExport std::string& message(); + + /*! + * @brief This function returns the maximum serialized size of an object + * depending on the buffer alignment. + * @param current_alignment Buffer alignment. + * @return Maximum serialized size. + */ + eProsima_user_DllExport static size_t getMaxCdrSerializedSize( + size_t current_alignment = 0); + + /*! + * @brief This function returns the serialized size of a data depending on the buffer alignment. + * @param data Data which is calculated its serialized size. + * @param current_alignment Buffer alignment. + * @return Serialized size. + */ + eProsima_user_DllExport static size_t getCdrSerializedSize( + const HelloWorld& data, + size_t current_alignment = 0); + + + /*! + * @brief This function serializes an object using CDR serialization. + * @param cdr CDR serialization object. + */ + eProsima_user_DllExport void serialize( + eprosima::fastcdr::Cdr& cdr) const; + + /*! + * @brief This function deserializes an object using CDR serialization. + * @param cdr CDR serialization object. + */ + eProsima_user_DllExport void deserialize( + eprosima::fastcdr::Cdr& cdr); + + + + /*! + * @brief This function returns the maximum serialized size of the Key of an object + * depending on the buffer alignment. + * @param current_alignment Buffer alignment. + * @return Maximum serialized size. + */ + eProsima_user_DllExport static size_t getKeyMaxCdrSerializedSize( + size_t current_alignment = 0); + + /*! + * @brief This function tells you if the Key has been defined for this type + */ + eProsima_user_DllExport static bool isKeyDefined(); + + /*! + * @brief This function serializes the key members of an object using CDR serialization. + * @param cdr CDR serialization object. + */ + eProsima_user_DllExport void serializeKey( + eprosima::fastcdr::Cdr& cdr) const; + +private: + + uint32_t m_index; + std::string m_message; +}; + +#endif // _FAST_DDS_GENERATED_HELLOWORLD_H_ \ No newline at end of file diff --git a/examples/C++/DDS/ContentFilterTopic/HelloWorld.idl b/examples/C++/DDS/ContentFilterTopic/HelloWorld.idl new file mode 100644 index 00000000000..0fd2c355aee --- /dev/null +++ b/examples/C++/DDS/ContentFilterTopic/HelloWorld.idl @@ -0,0 +1,5 @@ +struct HelloWorld +{ + unsigned long index; + string message; +}; diff --git a/examples/C++/DDS/ContentFilterTopic/HelloWorldPubSubTypes.cxx b/examples/C++/DDS/ContentFilterTopic/HelloWorldPubSubTypes.cxx new file mode 100644 index 00000000000..0741f6fded3 --- /dev/null +++ b/examples/C++/DDS/ContentFilterTopic/HelloWorldPubSubTypes.cxx @@ -0,0 +1,170 @@ +// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// 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. + +/*! + * @file HelloWorldPubSubTypes.cpp + * This header file contains the implementation of the serialization functions. + * + * This file was generated by the tool fastcdrgen. + */ + + +#include +#include + +#include "HelloWorldPubSubTypes.h" + +using SerializedPayload_t = eprosima::fastrtps::rtps::SerializedPayload_t; +using InstanceHandle_t = eprosima::fastrtps::rtps::InstanceHandle_t; + +HelloWorldPubSubType::HelloWorldPubSubType() +{ + setName("HelloWorld"); + auto type_size = HelloWorld::getMaxCdrSerializedSize(); + type_size += eprosima::fastcdr::Cdr::alignment(type_size, 4); /* possible submessage alignment */ + m_typeSize = static_cast(type_size) + 4; /*encapsulation*/ + m_isGetKeyDefined = HelloWorld::isKeyDefined(); + size_t keyLength = HelloWorld::getKeyMaxCdrSerializedSize() > 16 ? + HelloWorld::getKeyMaxCdrSerializedSize() : 16; + m_keyBuffer = reinterpret_cast(malloc(keyLength)); + memset(m_keyBuffer, 0, keyLength); +} + +HelloWorldPubSubType::~HelloWorldPubSubType() +{ + if (m_keyBuffer != nullptr) + { + free(m_keyBuffer); + } +} + +bool HelloWorldPubSubType::serialize( + void* data, + SerializedPayload_t* payload) +{ + HelloWorld* p_type = static_cast(data); + + // Object that manages the raw buffer. + eprosima::fastcdr::FastBuffer fastbuffer(reinterpret_cast(payload->data), payload->max_size); + // Object that serializes the data. + eprosima::fastcdr::Cdr ser(fastbuffer, eprosima::fastcdr::Cdr::DEFAULT_ENDIAN, eprosima::fastcdr::Cdr::DDS_CDR); + payload->encapsulation = ser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE : CDR_LE; + // Serialize encapsulation + ser.serialize_encapsulation(); + + try + { + // Serialize the object. + p_type->serialize(ser); + } + catch (eprosima::fastcdr::exception::NotEnoughMemoryException& /*exception*/) + { + return false; + } + + // Get the serialized length + payload->length = static_cast(ser.getSerializedDataLength()); + return true; +} + +bool HelloWorldPubSubType::deserialize( + SerializedPayload_t* payload, + void* data) +{ + try + { + //Convert DATA to pointer of your type + HelloWorld* p_type = static_cast(data); + + // Object that manages the raw buffer. + eprosima::fastcdr::FastBuffer fastbuffer(reinterpret_cast(payload->data), payload->length); + + // Object that deserializes the data. + eprosima::fastcdr::Cdr deser(fastbuffer, eprosima::fastcdr::Cdr::DEFAULT_ENDIAN, eprosima::fastcdr::Cdr::DDS_CDR); + + // Deserialize encapsulation. + deser.read_encapsulation(); + payload->encapsulation = deser.endianness() == eprosima::fastcdr::Cdr::BIG_ENDIANNESS ? CDR_BE : CDR_LE; + + // Deserialize the object. + p_type->deserialize(deser); + } + catch (eprosima::fastcdr::exception::NotEnoughMemoryException& /*exception*/) + { + return false; + } + + return true; +} + +std::function HelloWorldPubSubType::getSerializedSizeProvider( + void* data) +{ + return [data]() -> uint32_t + { + return static_cast(type::getCdrSerializedSize(*static_cast(data))) + + 4u /*encapsulation*/; + }; +} + +void* HelloWorldPubSubType::createData() +{ + return reinterpret_cast(new HelloWorld()); +} + +void HelloWorldPubSubType::deleteData( + void* data) +{ + delete(reinterpret_cast(data)); +} + +bool HelloWorldPubSubType::getKey( + void* data, + InstanceHandle_t* handle, + bool force_md5) +{ + if (!m_isGetKeyDefined) + { + return false; + } + + HelloWorld* p_type = static_cast(data); + + // Object that manages the raw buffer. + eprosima::fastcdr::FastBuffer fastbuffer(reinterpret_cast(m_keyBuffer), + HelloWorld::getKeyMaxCdrSerializedSize()); + + // Object that serializes the data. + eprosima::fastcdr::Cdr ser(fastbuffer, eprosima::fastcdr::Cdr::BIG_ENDIANNESS); + p_type->serializeKey(ser); + if (force_md5 || HelloWorld::getKeyMaxCdrSerializedSize() > 16) + { + m_md5.init(); + m_md5.update(m_keyBuffer, static_cast(ser.getSerializedDataLength())); + m_md5.finalize(); + for (uint8_t i = 0; i < 16; ++i) + { + handle->value[i] = m_md5.digest[i]; + } + } + else + { + for (uint8_t i = 0; i < 16; ++i) + { + handle->value[i] = m_keyBuffer[i]; + } + } + return true; +} + diff --git a/examples/C++/DDS/ContentFilterTopic/HelloWorldPubSubTypes.h b/examples/C++/DDS/ContentFilterTopic/HelloWorldPubSubTypes.h new file mode 100644 index 00000000000..8b2348be67c --- /dev/null +++ b/examples/C++/DDS/ContentFilterTopic/HelloWorldPubSubTypes.h @@ -0,0 +1,101 @@ +// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// 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. + +/*! + * @file HelloWorldPubSubTypes.h + * This header file contains the declaration of the serialization functions. + * + * This file was generated by the tool fastcdrgen. + */ + + +#ifndef _FAST_DDS_GENERATED_HELLOWORLD_PUBSUBTYPES_H_ +#define _FAST_DDS_GENERATED_HELLOWORLD_PUBSUBTYPES_H_ + +#include +#include + +#include "HelloWorld.h" + +#if !defined(GEN_API_VER) || (GEN_API_VER != 1) +#error \ + Generated HelloWorld is not compatible with current installed Fast DDS. Please, regenerate it with fastddsgen. +#endif // GEN_API_VER + +/*! + * @brief This class represents the TopicDataType of the type HelloWorld defined by the user in the IDL file. + * @ingroup HELLOWORLD + */ +class HelloWorldPubSubType : public eprosima::fastdds::dds::TopicDataType +{ +public: + + typedef HelloWorld type; + + eProsima_user_DllExport HelloWorldPubSubType(); + + eProsima_user_DllExport virtual ~HelloWorldPubSubType(); + + eProsima_user_DllExport virtual bool serialize( + void* data, + eprosima::fastrtps::rtps::SerializedPayload_t* payload) override; + + eProsima_user_DllExport virtual bool deserialize( + eprosima::fastrtps::rtps::SerializedPayload_t* payload, + void* data) override; + + eProsima_user_DllExport virtual std::function getSerializedSizeProvider( + void* data) override; + + eProsima_user_DllExport virtual bool getKey( + void* data, + eprosima::fastrtps::rtps::InstanceHandle_t* ihandle, + bool force_md5 = false) override; + + eProsima_user_DllExport virtual void* createData() override; + + eProsima_user_DllExport virtual void deleteData( + void* data) override; + +#ifdef TOPIC_DATA_TYPE_API_HAS_IS_BOUNDED + eProsima_user_DllExport inline bool is_bounded() const override + { + return false; + } + +#endif // TOPIC_DATA_TYPE_API_HAS_IS_BOUNDED + +#ifdef TOPIC_DATA_TYPE_API_HAS_IS_PLAIN + eProsima_user_DllExport inline bool is_plain() const override + { + return false; + } + +#endif // TOPIC_DATA_TYPE_API_HAS_IS_PLAIN + +#ifdef TOPIC_DATA_TYPE_API_HAS_CONSTRUCT_SAMPLE + eProsima_user_DllExport inline bool construct_sample( + void* memory) const override + { + (void)memory; + return false; + } + +#endif // TOPIC_DATA_TYPE_API_HAS_CONSTRUCT_SAMPLE + + MD5 m_md5; + unsigned char* m_keyBuffer; +}; + +#endif // _FAST_DDS_GENERATED_HELLOWORLD_PUBSUBTYPES_H_ \ No newline at end of file diff --git a/examples/C++/DDS/ContentFilterTopic/HelloWorldTypeObject.cxx b/examples/C++/DDS/ContentFilterTopic/HelloWorldTypeObject.cxx new file mode 100644 index 00000000000..e4cd82ed3ba --- /dev/null +++ b/examples/C++/DDS/ContentFilterTopic/HelloWorldTypeObject.cxx @@ -0,0 +1,248 @@ +// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// 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. + +/*! + * @file HelloWorldTypeObject.cpp + * This source file contains the definition of the described types in the IDL file. + * + * This file was generated by the tool gen. + */ + +#ifdef _WIN32 +// Remove linker warning LNK4221 on Visual Studio +namespace { char dummy; } +#endif + +#include "HelloWorld.h" +#include "HelloWorldTypeObject.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace eprosima::fastrtps::rtps; + +void registerHelloWorldTypes() +{ + TypeObjectFactory *factory = TypeObjectFactory::get_instance(); + factory->add_type_object("HelloWorld", GetHelloWorldIdentifier(true), + GetHelloWorldObject(true)); + factory->add_type_object("HelloWorld", GetHelloWorldIdentifier(false), + GetHelloWorldObject(false)); + +} + +const TypeIdentifier* GetHelloWorldIdentifier(bool complete) +{ + const TypeIdentifier * c_identifier = TypeObjectFactory::get_instance()->get_type_identifier("HelloWorld", complete); + if (c_identifier != nullptr && (!complete || c_identifier->_d() == EK_COMPLETE)) + { + return c_identifier; + } + + GetHelloWorldObject(complete); // Generated inside + return TypeObjectFactory::get_instance()->get_type_identifier("HelloWorld", complete); +} + +const TypeObject* GetHelloWorldObject(bool complete) +{ + const TypeObject* c_type_object = TypeObjectFactory::get_instance()->get_type_object("HelloWorld", complete); + if (c_type_object != nullptr) + { + return c_type_object; + } + else if (complete) + { + return GetCompleteHelloWorldObject(); + } + //else + return GetMinimalHelloWorldObject(); +} + +const TypeObject* GetMinimalHelloWorldObject() +{ + const TypeObject* c_type_object = TypeObjectFactory::get_instance()->get_type_object("HelloWorld", false); + if (c_type_object != nullptr) + { + return c_type_object; + } + + TypeObject *type_object = new TypeObject(); + type_object->_d(EK_MINIMAL); + type_object->minimal()._d(TK_STRUCTURE); + + type_object->minimal().struct_type().struct_flags().IS_FINAL(false); + type_object->minimal().struct_type().struct_flags().IS_APPENDABLE(false); + type_object->minimal().struct_type().struct_flags().IS_MUTABLE(false); + type_object->minimal().struct_type().struct_flags().IS_NESTED(false); + type_object->minimal().struct_type().struct_flags().IS_AUTOID_HASH(false); // Unsupported + + MemberId memberId = 0; + MinimalStructMember mst_index; + mst_index.common().member_id(memberId++); + mst_index.common().member_flags().TRY_CONSTRUCT1(false); // Unsupported + mst_index.common().member_flags().TRY_CONSTRUCT2(false); // Unsupported + mst_index.common().member_flags().IS_EXTERNAL(false); // Unsupported + mst_index.common().member_flags().IS_OPTIONAL(false); + mst_index.common().member_flags().IS_MUST_UNDERSTAND(false); + mst_index.common().member_flags().IS_KEY(false); + mst_index.common().member_flags().IS_DEFAULT(false); // Doesn't apply + mst_index.common().member_type_id(*TypeObjectFactory::get_instance()->get_type_identifier("uint32_t", false)); + + MD5 index_hash("index"); + for(int i = 0; i < 4; ++i) + { + mst_index.detail().name_hash()[i] = index_hash.digest[i]; + } + type_object->minimal().struct_type().member_seq().emplace_back(mst_index); + + MinimalStructMember mst_message; + mst_message.common().member_id(memberId++); + mst_message.common().member_flags().TRY_CONSTRUCT1(false); // Unsupported + mst_message.common().member_flags().TRY_CONSTRUCT2(false); // Unsupported + mst_message.common().member_flags().IS_EXTERNAL(false); // Unsupported + mst_message.common().member_flags().IS_OPTIONAL(false); + mst_message.common().member_flags().IS_MUST_UNDERSTAND(false); + mst_message.common().member_flags().IS_KEY(false); + mst_message.common().member_flags().IS_DEFAULT(false); // Doesn't apply + mst_message.common().member_type_id(*TypeObjectFactory::get_instance()->get_string_identifier(255, false)); + + + MD5 message_hash("message"); + for(int i = 0; i < 4; ++i) + { + mst_message.detail().name_hash()[i] = message_hash.digest[i]; + } + type_object->minimal().struct_type().member_seq().emplace_back(mst_message); + + + // Header + // TODO Inheritance + //type_object->minimal().struct_type().header().base_type()._d(EK_MINIMAL); + //type_object->minimal().struct_type().header().base_type().equivalence_hash()[0..13]; + + TypeIdentifier identifier; + identifier._d(EK_MINIMAL); + + SerializedPayload_t payload(static_cast( + MinimalStructType::getCdrSerializedSize(type_object->minimal().struct_type()) + 4)); + eprosima::fastcdr::FastBuffer fastbuffer((char*) payload.data, payload.max_size); + // Fixed endian (Page 221, EquivalenceHash definition of Extensible and Dynamic Topic Types for DDS document) + eprosima::fastcdr::Cdr ser( + fastbuffer, eprosima::fastcdr::Cdr::LITTLE_ENDIANNESS, + eprosima::fastcdr::Cdr::DDS_CDR); // Object that serializes the data. + payload.encapsulation = CDR_LE; + + type_object->serialize(ser); + payload.length = (uint32_t)ser.getSerializedDataLength(); //Get the serialized length + MD5 objectHash; + objectHash.update((char*)payload.data, payload.length); + objectHash.finalize(); + for(int i = 0; i < 14; ++i) + { + identifier.equivalence_hash()[i] = objectHash.digest[i]; + } + + TypeObjectFactory::get_instance()->add_type_object("HelloWorld", &identifier, type_object); + delete type_object; + return TypeObjectFactory::get_instance()->get_type_object("HelloWorld", false); +} + +const TypeObject* GetCompleteHelloWorldObject() +{ + const TypeObject* c_type_object = TypeObjectFactory::get_instance()->get_type_object("HelloWorld", true); + if (c_type_object != nullptr && c_type_object->_d() == EK_COMPLETE) + { + return c_type_object; + } + + TypeObject *type_object = new TypeObject(); + type_object->_d(EK_COMPLETE); + type_object->complete()._d(TK_STRUCTURE); + + type_object->complete().struct_type().struct_flags().IS_FINAL(false); + type_object->complete().struct_type().struct_flags().IS_APPENDABLE(false); + type_object->complete().struct_type().struct_flags().IS_MUTABLE(false); + type_object->complete().struct_type().struct_flags().IS_NESTED(false); + type_object->complete().struct_type().struct_flags().IS_AUTOID_HASH(false); // Unsupported + + MemberId memberId = 0; + CompleteStructMember cst_index; + cst_index.common().member_id(memberId++); + cst_index.common().member_flags().TRY_CONSTRUCT1(false); // Unsupported + cst_index.common().member_flags().TRY_CONSTRUCT2(false); // Unsupported + cst_index.common().member_flags().IS_EXTERNAL(false); // Unsupported + cst_index.common().member_flags().IS_OPTIONAL(false); + cst_index.common().member_flags().IS_MUST_UNDERSTAND(false); + cst_index.common().member_flags().IS_KEY(false); + cst_index.common().member_flags().IS_DEFAULT(false); // Doesn't apply + cst_index.common().member_type_id(*TypeObjectFactory::get_instance()->get_type_identifier("uint32_t", false)); + + cst_index.detail().name("index"); + + type_object->complete().struct_type().member_seq().emplace_back(cst_index); + + CompleteStructMember cst_message; + cst_message.common().member_id(memberId++); + cst_message.common().member_flags().TRY_CONSTRUCT1(false); // Unsupported + cst_message.common().member_flags().TRY_CONSTRUCT2(false); // Unsupported + cst_message.common().member_flags().IS_EXTERNAL(false); // Unsupported + cst_message.common().member_flags().IS_OPTIONAL(false); + cst_message.common().member_flags().IS_MUST_UNDERSTAND(false); + cst_message.common().member_flags().IS_KEY(false); + cst_message.common().member_flags().IS_DEFAULT(false); // Doesn't apply + cst_message.common().member_type_id(*TypeObjectFactory::get_instance()->get_string_identifier(255, false)); + + + cst_message.detail().name("message"); + + type_object->complete().struct_type().member_seq().emplace_back(cst_message); + + + // Header + type_object->complete().struct_type().header().detail().type_name("HelloWorld"); + // TODO inheritance + + + TypeIdentifier identifier; + identifier._d(EK_COMPLETE); + + SerializedPayload_t payload(static_cast( + CompleteStructType::getCdrSerializedSize(type_object->complete().struct_type()) + 4)); + eprosima::fastcdr::FastBuffer fastbuffer((char*) payload.data, payload.max_size); + // Fixed endian (Page 221, EquivalenceHash definition of Extensible and Dynamic Topic Types for DDS document) + eprosima::fastcdr::Cdr ser( + fastbuffer, eprosima::fastcdr::Cdr::LITTLE_ENDIANNESS, + eprosima::fastcdr::Cdr::DDS_CDR); // Object that serializes the data. + payload.encapsulation = CDR_LE; + + type_object->serialize(ser); + payload.length = (uint32_t)ser.getSerializedDataLength(); //Get the serialized length + MD5 objectHash; + objectHash.update((char*)payload.data, payload.length); + objectHash.finalize(); + for(int i = 0; i < 14; ++i) + { + identifier.equivalence_hash()[i] = objectHash.digest[i]; + } + + TypeObjectFactory::get_instance()->add_type_object("HelloWorld", &identifier, type_object); + delete type_object; + return TypeObjectFactory::get_instance()->get_type_object("HelloWorld", true); +} diff --git a/examples/C++/DDS/ContentFilterTopic/HelloWorldTypeObject.h b/examples/C++/DDS/ContentFilterTopic/HelloWorldTypeObject.h new file mode 100644 index 00000000000..d6b4fbe75c1 --- /dev/null +++ b/examples/C++/DDS/ContentFilterTopic/HelloWorldTypeObject.h @@ -0,0 +1,63 @@ +// Copyright 2016 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// 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. + +/*! + * @file HelloWorldTypeObject.h + * This header file contains the declaration of the described types in the IDL file. + * + * This file was generated by the tool gen. + */ + +#ifndef _FAST_DDS_GENERATED_HELLOWORLD_TYPE_OBJECT_H_ +#define _FAST_DDS_GENERATED_HELLOWORLD_TYPE_OBJECT_H_ + + +#include +#include + +#if defined(_WIN32) +#if defined(EPROSIMA_USER_DLL_EXPORT) +#define eProsima_user_DllExport __declspec( dllexport ) +#else +#define eProsima_user_DllExport +#endif +#else +#define eProsima_user_DllExport +#endif + +#if defined(_WIN32) +#if defined(EPROSIMA_USER_DLL_EXPORT) +#if defined(HelloWorld_SOURCE) +#define HelloWorld_DllAPI __declspec( dllexport ) +#else +#define HelloWorld_DllAPI __declspec( dllimport ) +#endif // HelloWorld_SOURCE +#else +#define HelloWorld_DllAPI +#endif +#else +#define HelloWorld_DllAPI +#endif // _WIN32 + +using namespace eprosima::fastrtps::types; + +eProsima_user_DllExport void registerHelloWorldTypes(); + +eProsima_user_DllExport const TypeIdentifier* GetHelloWorldIdentifier(bool complete = false); +eProsima_user_DllExport const TypeObject* GetHelloWorldObject(bool complete = false); +eProsima_user_DllExport const TypeObject* GetMinimalHelloWorldObject(); +eProsima_user_DllExport const TypeObject* GetCompleteHelloWorldObject(); + + +#endif // _FAST_DDS_GENERATED_HELLOWORLD_TYPE_OBJECT_H_ \ No newline at end of file From 0d7682b1954de724620a50c99c22f6a3b10cf980 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Gonz=C3=A1lez=20Moreno?= Date: Wed, 23 Mar 2022 11:50:30 +0100 Subject: [PATCH 02/17] Refs #13791. Add CustomFilter example MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ricardo González Moreno --- .../C++/DDS/ContentFilterTopic/CMakeLists.txt | 23 ++- .../CustomFilterPublisher.cpp | 185 ++++++++++++++++++ .../CustomFilterPublisher.hpp | 96 +++++++++ .../CustomFilterSubscriber.cpp | 171 ++++++++++++++++ .../CustomFilterSubscriber.hpp | 89 +++++++++ .../ContentFilterTopic/CustomFilter_main.cpp | 86 ++++++++ .../DefaultSQLFilterPublisher.hpp | 2 +- .../DefaultSQLFilter_main.cpp | 2 +- .../DDS/ContentFilterTopic/MyCustomFilter.hpp | 61 ++++++ .../MyCustomFilterFactory.hpp | 67 +++++++ 10 files changed, 771 insertions(+), 11 deletions(-) create mode 100644 examples/C++/DDS/ContentFilterTopic/CustomFilterPublisher.cpp create mode 100644 examples/C++/DDS/ContentFilterTopic/CustomFilterPublisher.hpp create mode 100644 examples/C++/DDS/ContentFilterTopic/CustomFilterSubscriber.cpp create mode 100644 examples/C++/DDS/ContentFilterTopic/CustomFilterSubscriber.hpp create mode 100644 examples/C++/DDS/ContentFilterTopic/CustomFilter_main.cpp create mode 100644 examples/C++/DDS/ContentFilterTopic/MyCustomFilter.hpp create mode 100644 examples/C++/DDS/ContentFilterTopic/MyCustomFilterFactory.hpp diff --git a/examples/C++/DDS/ContentFilterTopic/CMakeLists.txt b/examples/C++/DDS/ContentFilterTopic/CMakeLists.txt index aa50cb19365..7e195f7f276 100644 --- a/examples/C++/DDS/ContentFilterTopic/CMakeLists.txt +++ b/examples/C++/DDS/ContentFilterTopic/CMakeLists.txt @@ -38,6 +38,11 @@ set(CFT_DSF_SOURCES DefaultSQLFilterSubscriber.cpp DefaultSQLFilter_main.cpp) +set(CFT_CF_SOURCES + CustomFilterPublisher.cpp + CustomFilterSubscriber.cpp + CustomFilter_main.cpp) + add_executable(DefaultSQLFilter ${CFT_COMMON_SOURCES} ${CFT_DSF_SOURCES}) target_compile_definitions(DefaultSQLFilter PRIVATE @@ -49,12 +54,12 @@ target_link_libraries(DefaultSQLFilter fastrtps fastcdr) install(TARGETS DefaultSQLFilter RUNTIME DESTINATION examples/C++/DDS/ContentFilterTopic/${BIN_INSTALL_DIR}) -#add_executable(CustomFilter ${CFT_COMMON_SOURCES}) -#target_compile_definitions(CustomFilter PRIVATE -# $<$>,$>:__DEBUG> -# $<$:__INTERNALDEBUG> # Internal debug activated. -#) -#target_compile_features(CustomFilter PRIVATE cxx_std_11) -#target_link_libraries(CustomFilter fastrtps fastcdr) -#install(TARGETS CustomFilter -# RUNTIME DESTINATION examples/C++/DDS/ContentFilterTopic/${BIN_INSTALL_DIR}) +add_executable(CustomFilter ${CFT_COMMON_SOURCES} ${CFT_CF_SOURCES}) +target_compile_definitions(CustomFilter PRIVATE + $<$>,$>:__DEBUG> + $<$:__INTERNALDEBUG> # Internal debug activated. +) +target_compile_features(CustomFilter PRIVATE cxx_std_11) +target_link_libraries(CustomFilter fastrtps fastcdr) +install(TARGETS CustomFilter + RUNTIME DESTINATION examples/C++/DDS/ContentFilterTopic/${BIN_INSTALL_DIR}) diff --git a/examples/C++/DDS/ContentFilterTopic/CustomFilterPublisher.cpp b/examples/C++/DDS/ContentFilterTopic/CustomFilterPublisher.cpp new file mode 100644 index 00000000000..1ddb004a166 --- /dev/null +++ b/examples/C++/DDS/ContentFilterTopic/CustomFilterPublisher.cpp @@ -0,0 +1,185 @@ +// Copyright 2022 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// 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. + +/** + * @file CustomFilterPublisher.cpp + * + */ + +#include "CustomFilterPublisher.hpp" +#include +#include +#include +#include +#include +#include +#include + +#include + +using namespace eprosima::fastdds::dds; + +CustomFilterPublisher::CustomFilterPublisher() + : participant_(nullptr) + , publisher_(nullptr) + , topic_(nullptr) + , writer_(nullptr) + , type_(new HelloWorldPubSubType()) +{ +} + +bool CustomFilterPublisher::init() +{ + hello_.index(0); + hello_.message("HelloWorld"); + DomainParticipantQos pqos; + pqos.name("Participant_pub"); + participant_ = DomainParticipantFactory::get_instance()->create_participant(0, pqos); + + if (participant_ == nullptr) + { + return false; + } + + //REGISTER THE TYPE + type_.register_type(participant_); + + //CREATE THE PUBLISHER + publisher_ = participant_->create_publisher(PUBLISHER_QOS_DEFAULT, nullptr); + + if (publisher_ == nullptr) + { + return false; + } + + topic_ = participant_->create_topic("HelloWorldTopic", "HelloWorld", TOPIC_QOS_DEFAULT); + + if (topic_ == nullptr) + { + return false; + } + + // CREATE THE WRITER + writer_ = publisher_->create_datawriter(topic_, DATAWRITER_QOS_DEFAULT, &listener_); + + if (writer_ == nullptr) + { + return false; + } + return true; +} + +CustomFilterPublisher::~CustomFilterPublisher() +{ + if (writer_ != nullptr) + { + publisher_->delete_datawriter(writer_); + } + if (publisher_ != nullptr) + { + participant_->delete_publisher(publisher_); + } + if (topic_ != nullptr) + { + participant_->delete_topic(topic_); + } + DomainParticipantFactory::get_instance()->delete_participant(participant_); +} + +void CustomFilterPublisher::PubListener::on_publication_matched( + eprosima::fastdds::dds::DataWriter*, + const eprosima::fastdds::dds::PublicationMatchedStatus& info) +{ + if (info.current_count_change == 1) + { + matched_ = info.total_count; + firstConnected_ = true; + std::cout << "Publisher matched." << std::endl; + } + else if (info.current_count_change == -1) + { + matched_ = info.total_count; + std::cout << "Publisher unmatched." << std::endl; + } + else + { + std::cout << info.current_count_change + << " is not a valid value for PublicationMatchedStatus current count change" << std::endl; + } +} + +void CustomFilterPublisher::runThread( + uint32_t samples, + uint32_t sleep) +{ + if (samples == 0) + { + while (!stop_) + { + if (publish(false)) + { + std::cout << "Message: " << hello_.message() << " with index: " << hello_.index() + << " SENT" << std::endl; + } + std::this_thread::sleep_for(std::chrono::milliseconds(sleep)); + } + } + else + { + for (uint32_t i = 0; i < samples; ++i) + { + if (!publish()) + { + --i; + } + else + { + std::cout << "Message: " << hello_.message() << " with index: " << hello_.index() + << " SENT" << std::endl; + } + std::this_thread::sleep_for(std::chrono::milliseconds(sleep)); + } + } +} + +void CustomFilterPublisher::run( + uint32_t samples, + uint32_t sleep) +{ + stop_ = false; + std::thread thread(&CustomFilterPublisher::runThread, this, samples, sleep); + if (samples == 0) + { + std::cout << "Publisher running. Please press enter to stop the Publisher at any time." << std::endl; + std::cin.ignore(); + stop_ = true; + } + else + { + std::cout << "Publisher running " << samples << " samples." << std::endl; + } + thread.join(); +} + +bool CustomFilterPublisher::publish( + bool waitForListener) +{ + if (listener_.firstConnected_ || !waitForListener || listener_.matched_ > 0) + { + hello_.index(hello_.index() + 1); + writer_->write(&hello_); + return true; + } + return false; +} diff --git a/examples/C++/DDS/ContentFilterTopic/CustomFilterPublisher.hpp b/examples/C++/DDS/ContentFilterTopic/CustomFilterPublisher.hpp new file mode 100644 index 00000000000..7e0a2ce0e26 --- /dev/null +++ b/examples/C++/DDS/ContentFilterTopic/CustomFilterPublisher.hpp @@ -0,0 +1,96 @@ +// Copyright 2022 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// 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. + +/** + * @file CustomFilterPublisher.hpp + * + */ + +#ifndef _DEFAULTSQLFILTERPUBLISHER_H_ +#define _DEFAULTSQLFILTERPUBLISHER_H_ + +#include "HelloWorldPubSubTypes.h" + +#include +#include +#include + +class CustomFilterPublisher +{ +public: + + CustomFilterPublisher(); + + virtual ~CustomFilterPublisher(); + + //!Initialize + bool init(); + + //!Publish a sample + bool publish( + bool waitForListener = true); + + //!Run for number samples + void run( + uint32_t number, + uint32_t sleep); + +private: + + HelloWorld hello_; + + eprosima::fastdds::dds::DomainParticipant* participant_; + + eprosima::fastdds::dds::Publisher* publisher_; + + eprosima::fastdds::dds::Topic* topic_; + + eprosima::fastdds::dds::DataWriter* writer_; + + bool stop_; + + class PubListener : public eprosima::fastdds::dds::DataWriterListener + { + public: + + PubListener() + : matched_(0) + , firstConnected_(false) + { + } + + ~PubListener() override + { + } + + void on_publication_matched( + eprosima::fastdds::dds::DataWriter* writer, + const eprosima::fastdds::dds::PublicationMatchedStatus& info) override; + + int matched_; + + bool firstConnected_; + } + listener_; + + void runThread( + uint32_t number, + uint32_t sleep); + + eprosima::fastdds::dds::TypeSupport type_; +}; + + + +#endif // _DEFAULTSQLFILTERPUBLISHER_H_ diff --git a/examples/C++/DDS/ContentFilterTopic/CustomFilterSubscriber.cpp b/examples/C++/DDS/ContentFilterTopic/CustomFilterSubscriber.cpp new file mode 100644 index 00000000000..10b47a6425b --- /dev/null +++ b/examples/C++/DDS/ContentFilterTopic/CustomFilterSubscriber.cpp @@ -0,0 +1,171 @@ +// Copyright 2022 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// 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. + +/** + * @file CustomFilterSubscriber.cpp + * + */ + +#include "CustomFilterSubscriber.hpp" +#include +#include +#include +#include +#include +#include +#include + +using namespace eprosima::fastdds::dds; + +bool CustomFilterSubscriber::init() +{ + DomainParticipantQos pqos; + pqos.name("Participant_sub"); + participant_ = DomainParticipantFactory::get_instance()->create_participant(0, pqos); + + if (participant_ == nullptr) + { + return false; + } + + // Register the filter factory + if (ReturnCode_t::RETCODE_OK != + participant_->register_content_filter_factory("MY_CUSTOM_FILTER", &filter_factory)) + { + // Error + return false; + } + + //Register the type + type_.register_type(participant_); + + //CREATE THE SUBSCRIBER + subscriber_ = participant_->create_subscriber(SUBSCRIBER_QOS_DEFAULT, nullptr); + + if (subscriber_ == nullptr) + { + return false; + } + + //Create the topic + topic_ = participant_->create_topic( + "HelloWorldTopic", + "HelloWorld", + TOPIC_QOS_DEFAULT); + + if (topic_ == nullptr) + { + return false; + } + + // Create a ContentFilteredTopic using an expression with no parameters + std::string expression = " "; + std::vector parameters; + parameters.push_back("3"); + parameters.push_back("5"); + filter_topic_ = + participant_->create_contentfilteredtopic("HelloWorldFilteredTopic1", topic_, expression, parameters, + "MY_CUSTOM_FILTER"); + + if (nullptr == filter_topic_) + { + // Error + return false; + } + + // CREATE THE READER + DataReaderQos rqos = DATAREADER_QOS_DEFAULT; + rqos.reliability().kind = RELIABLE_RELIABILITY_QOS; + reader_ = subscriber_->create_datareader(filter_topic_, rqos, &listener_); + + if (reader_ == nullptr) + { + return false; + } + + return true; +} + +CustomFilterSubscriber::~CustomFilterSubscriber() +{ + if (reader_ != nullptr) + { + subscriber_->delete_datareader(reader_); + } + if (nullptr != filter_topic_) + { + participant_->delete_contentfilteredtopic(filter_topic_); + } + if (topic_ != nullptr) + { + participant_->delete_topic(topic_); + } + if (subscriber_ != nullptr) + { + participant_->delete_subscriber(subscriber_); + } + DomainParticipantFactory::get_instance()->delete_participant(participant_); +} + +void CustomFilterSubscriber::SubListener::on_subscription_matched( + DataReader*, + const SubscriptionMatchedStatus& info) +{ + if (info.current_count_change == 1) + { + matched_ = info.total_count; + std::cout << "Subscriber matched." << std::endl; + } + else if (info.current_count_change == -1) + { + matched_ = info.total_count; + std::cout << "Subscriber unmatched." << std::endl; + } + else + { + std::cout << info.current_count_change + << " is not a valid value for SubscriptionMatchedStatus current count change" << std::endl; + } +} + +void CustomFilterSubscriber::SubListener::on_data_available( + DataReader* reader) +{ + SampleInfo info; + if (reader->take_next_sample(&hello_, &info) == ReturnCode_t::RETCODE_OK) + { + if (info.instance_state == ALIVE_INSTANCE_STATE) + { + samples_++; + // Print your structure data here. + std::cout << "Message " << hello_.message() << " " << hello_.index() << " RECEIVED" << std::endl; + } + } +} + +void CustomFilterSubscriber::run() +{ + std::cout << "Subscriber running. Please press enter to stop the Subscriber" << std::endl; + std::cin.ignore(); +} + +void CustomFilterSubscriber::run( + uint32_t number) +{ + std::cout << "Subscriber running until " << number << "samples have been received" << std::endl; + while (number > listener_.samples_) + { + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + } +} diff --git a/examples/C++/DDS/ContentFilterTopic/CustomFilterSubscriber.hpp b/examples/C++/DDS/ContentFilterTopic/CustomFilterSubscriber.hpp new file mode 100644 index 00000000000..a0d104abee1 --- /dev/null +++ b/examples/C++/DDS/ContentFilterTopic/CustomFilterSubscriber.hpp @@ -0,0 +1,89 @@ +// Copyright 2021 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// 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. + +/** + * @file CustomFilterSubscriber.hpp + * + */ + +#ifndef _DEFAULTSQLFILTERSUBSCRIBER_HPP_ +#define _DEFAULTSQLFILTERSUBSCRIBER_HPP_ + +#include "HelloWorldPubSubTypes.h" +#include "MyCustomFilterFactory.hpp" + +#include +#include +#include +#include + +class CustomFilterSubscriber +{ +public: + + CustomFilterSubscriber() = default; + + virtual ~CustomFilterSubscriber(); + + //!Initialize the subscriber + bool init(); + + //!RUN the subscriber + void run(); + + //!Run the subscriber until number samples have been received. + void run( + uint32_t number); + +private: + + eprosima::fastdds::dds::DomainParticipant* participant_ = nullptr; + + eprosima::fastdds::dds::Subscriber* subscriber_ = nullptr; + + eprosima::fastdds::dds::Topic* topic_ = nullptr; + + eprosima::fastdds::dds::ContentFilteredTopic* filter_topic_ = nullptr; + + eprosima::fastdds::dds::DataReader* reader_ = nullptr; + + eprosima::fastdds::dds::TypeSupport type_ = eprosima::fastdds::dds::TypeSupport(new HelloWorldPubSubType()); + + MyCustomFilterFactory filter_factory; + + class SubListener : public eprosima::fastdds::dds::DataReaderListener + { + public: + + ~SubListener() override + { + } + + void on_data_available( + eprosima::fastdds::dds::DataReader* reader) override; + + void on_subscription_matched( + eprosima::fastdds::dds::DataReader* reader, + const eprosima::fastdds::dds::SubscriptionMatchedStatus& info) override; + + HelloWorld hello_; + + int matched_ = 0; + + uint32_t samples_ = 0; + } + listener_; +}; + +#endif // _DEFAULTSQLFILTERSUBSCRIBER_HPP_ diff --git a/examples/C++/DDS/ContentFilterTopic/CustomFilter_main.cpp b/examples/C++/DDS/ContentFilterTopic/CustomFilter_main.cpp new file mode 100644 index 00000000000..5f01443fc37 --- /dev/null +++ b/examples/C++/DDS/ContentFilterTopic/CustomFilter_main.cpp @@ -0,0 +1,86 @@ +// Copyright 2022 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// +// 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. + +/** + * @file CustomFilter_main.cpp + * + */ + +#include "CustomFilterPublisher.hpp" +#include "CustomFilterSubscriber.hpp" + +#include + +#include + +using eprosima::fastdds::dds::Log; + +int main( + int argc, + char** argv) +{ + std::cout << "Starting " << std::endl; + int type = 1; + int count = 10; + int sleep = 100; + if (argc > 1) + { + if (strcmp(argv[1], "publisher") == 0) + { + type = 1; + if (argc >= 3) + { + count = atoi(argv[2]); + if (argc == 4) + { + sleep = atoi(argv[3]); + } + } + } + else if (strcmp(argv[1], "subscriber") == 0) + { + type = 2; + } + } + else + { + std::cout << "publisher OR subscriber argument needed" << std::endl; + Log::Reset(); + return 0; + } + + switch (type) + { + case 1: + { + CustomFilterPublisher mypub; + if (mypub.init()) + { + mypub.run(static_cast(count), static_cast(sleep)); + } + break; + } + case 2: + { + CustomFilterSubscriber mysub; + if (mysub.init()) + { + mysub.run(); + } + break; + } + } + Log::Reset(); + return 0; +} diff --git a/examples/C++/DDS/ContentFilterTopic/DefaultSQLFilterPublisher.hpp b/examples/C++/DDS/ContentFilterTopic/DefaultSQLFilterPublisher.hpp index ca75a26372b..2f108ba49a3 100644 --- a/examples/C++/DDS/ContentFilterTopic/DefaultSQLFilterPublisher.hpp +++ b/examples/C++/DDS/ContentFilterTopic/DefaultSQLFilterPublisher.hpp @@ -13,7 +13,7 @@ // limitations under the License. /** - * @file DefaultSQFilterPublisher.hpp + * @file DefaultSQLFilterPublisher.hpp * */ diff --git a/examples/C++/DDS/ContentFilterTopic/DefaultSQLFilter_main.cpp b/examples/C++/DDS/ContentFilterTopic/DefaultSQLFilter_main.cpp index 8a23a239a51..9c9c7657352 100644 --- a/examples/C++/DDS/ContentFilterTopic/DefaultSQLFilter_main.cpp +++ b/examples/C++/DDS/ContentFilterTopic/DefaultSQLFilter_main.cpp @@ -13,7 +13,7 @@ // limitations under the License. /** - * @file HelloWorld_main.cpp + * @file DefaultSQLFilter_main.cpp * */ diff --git a/examples/C++/DDS/ContentFilterTopic/MyCustomFilter.hpp b/examples/C++/DDS/ContentFilterTopic/MyCustomFilter.hpp new file mode 100644 index 00000000000..979107cbd4d --- /dev/null +++ b/examples/C++/DDS/ContentFilterTopic/MyCustomFilter.hpp @@ -0,0 +1,61 @@ +#ifndef _MYCUSTOMFILTER_HPP_ +#define _MYCUSTOMFILTER_HPP_ + +#include + +#include + +class MyCustomFilter : public eprosima::fastdds::dds::IContentFilter +{ +public: + + MyCustomFilter( + int low_mark, + int high_mark) + : low_mark_(low_mark) + , high_mark_(high_mark) + { + } + + virtual ~MyCustomFilter() = default; + + bool evaluate( + const SerializedPayload& payload, + const FilterSampleInfo& /*sample_info*/, + const GUID_t& /*reader_guid*/) const override + { + // Deserialize the `index` field from the serialized sample. + eprosima::fastcdr::FastBuffer fastbuffer(reinterpret_cast(payload.data), payload.length); + eprosima::fastcdr::Cdr deser(fastbuffer, eprosima::fastcdr::Cdr::DEFAULT_ENDIAN, + eprosima::fastcdr::Cdr::DDS_CDR); + // Deserialize encapsulation. + deser.read_encapsulation(); + uint32_t index = 0; + + // Deserialize `index` field. + try + { + deser >> index; + } + catch (eprosima::fastcdr::exception::NotEnoughMemoryException& /*exception*/) + { + return false; + } + + // Custom filter: reject samples where index > low_mark_ and index < high_mark_. + if (index < low_mark_ || index > high_mark_) + { + return true; + } + + return false; + } + +private: + + uint32_t low_mark_ = 0; + uint32_t high_mark_ = 0; + +}; + +#endif // _MYCUSTOMFILTER_HPP_ diff --git a/examples/C++/DDS/ContentFilterTopic/MyCustomFilterFactory.hpp b/examples/C++/DDS/ContentFilterTopic/MyCustomFilterFactory.hpp new file mode 100644 index 00000000000..fb3451954ce --- /dev/null +++ b/examples/C++/DDS/ContentFilterTopic/MyCustomFilterFactory.hpp @@ -0,0 +1,67 @@ +#ifndef _MYCUSTOMFILTERFACTORY_HPP_ +#define _MYCUSTOMFILTERFACTORY_HPP_ + +#include "MyCustomFilter.hpp" + +#include + +class MyCustomFilterFactory : public eprosima::fastdds::dds::IContentFilterFactory +{ +public: + + eprosima::fastrtps::types::ReturnCode_t create_content_filter( + const char* filter_class_name, // My custom filter class name is 'MY_CUSTOM_FILTER'. + const char* type_name, // This custom filter only supports one type: 'HelloWorld'. + const eprosima::fastdds::dds::TopicDataType* /*data_type*/, // Not used in this implementation. + const char* /*filter_expression*/, // This Custom Filter doesn't implement a filter expression. + const ParameterSeq& filter_parameters, // Always need two parameters to be set: low_mark and high_mark. + eprosima::fastdds::dds::IContentFilter*& filter_instance) override + { + // Check the ContentFilteredTopic should be created by my factory. + if (0 != strcmp(filter_class_name, "MY_CUSTOM_FILTER")) + { + return ReturnCode_t::RETCODE_BAD_PARAMETER; + } + + // Check the ContentFilteredTopic is created for the unique type this Custom Filter supports. + if (0 != strcmp(type_name, "HelloWorld")) + { + return ReturnCode_t::RETCODE_BAD_PARAMETER; + } + + // Checks there were set the two mandatory filter parameters. + if (2 != filter_parameters.length()) + { + return ReturnCode_t::RETCODE_BAD_PARAMETER; + } + + // If there is an update, delete previous instance. + if (nullptr != filter_instance) + { + delete(dynamic_cast(filter_instance)); + } + + // Instantiation of the Custom Filter. + filter_instance = new MyCustomFilter(std::stoi(filter_parameters[0]), std::stoi(filter_parameters[1])); + + return ReturnCode_t::RETCODE_OK; + } + + eprosima::fastrtps::types::ReturnCode_t delete_content_filter( + const char* filter_class_name, + eprosima::fastdds::dds::IContentFilter* filter_instance) override + { + // Check the ContentFilteredTopic should be created by my factory. + if (0 != strcmp(filter_class_name, "MY_CUSTOM_FILTER")) + { + return ReturnCode_t::RETCODE_BAD_PARAMETER; + } + + // Deletion of the Custom Filter. + delete(dynamic_cast(filter_instance)); + + return ReturnCode_t::RETCODE_OK; + } + +}; +#endif // _MYCUSTOMFILTERFACTORY_HPP_ From 51e0cc1e69d211e5c65083d58809b7dc464852fb Mon Sep 17 00:00:00 2001 From: JLBuenoLopez-eProsima Date: Wed, 6 Apr 2022 12:26:52 +0200 Subject: [PATCH 03/17] Refs #14220: rename example. First step to unify both examples into the same one with an user option indicating which filter to use (default SQL or custom one) Signed-off-by: JLBuenoLopez-eProsima --- examples/C++/DDS/CMakeLists.txt | 2 +- .../DefaultSQLFilterPublisher.cpp | 185 ------------------ .../DefaultSQLFilterPublisher.hpp | 96 --------- .../DefaultSQLFilterSubscriber.cpp | 162 --------------- .../DefaultSQLFilterSubscriber.hpp | 86 -------- .../DefaultSQLFilter_main.cpp | 86 -------- .../CMakeLists.txt | 36 +--- .../ContentFilteredTopicExamplePublisher.cpp} | 2 +- .../ContentFilteredTopicExamplePublisher.hpp} | 4 +- ...ContentFilteredTopicExampleSubscriber.cpp} | 2 +- ...ContentFilteredTopicExampleSubscriber.hpp} | 0 .../ContentFilteredTopicExample_main.cpp} | 4 +- .../HelloWorld.cxx | 0 .../HelloWorld.h | 0 .../HelloWorld.idl | 0 .../HelloWorldPubSubTypes.cxx | 0 .../HelloWorldPubSubTypes.h | 0 .../HelloWorldTypeObject.cxx | 0 .../HelloWorldTypeObject.h | 0 .../MyCustomFilter.hpp | 0 .../MyCustomFilterFactory.hpp | 0 21 files changed, 15 insertions(+), 650 deletions(-) delete mode 100644 examples/C++/DDS/ContentFilterTopic/DefaultSQLFilterPublisher.cpp delete mode 100644 examples/C++/DDS/ContentFilterTopic/DefaultSQLFilterPublisher.hpp delete mode 100644 examples/C++/DDS/ContentFilterTopic/DefaultSQLFilterSubscriber.cpp delete mode 100644 examples/C++/DDS/ContentFilterTopic/DefaultSQLFilterSubscriber.hpp delete mode 100644 examples/C++/DDS/ContentFilterTopic/DefaultSQLFilter_main.cpp rename examples/C++/DDS/{ContentFilterTopic => ContentFilteredTopicExample}/CMakeLists.txt (52%) rename examples/C++/DDS/{ContentFilterTopic/CustomFilterPublisher.cpp => ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.cpp} (98%) rename examples/C++/DDS/{ContentFilterTopic/CustomFilterPublisher.hpp => ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.hpp} (97%) rename examples/C++/DDS/{ContentFilterTopic/CustomFilterSubscriber.cpp => ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.cpp} (98%) rename examples/C++/DDS/{ContentFilterTopic/CustomFilterSubscriber.hpp => ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.hpp} (100%) rename examples/C++/DDS/{ContentFilterTopic/CustomFilter_main.cpp => ContentFilteredTopicExample/ContentFilteredTopicExample_main.cpp} (95%) rename examples/C++/DDS/{ContentFilterTopic => ContentFilteredTopicExample}/HelloWorld.cxx (100%) rename examples/C++/DDS/{ContentFilterTopic => ContentFilteredTopicExample}/HelloWorld.h (100%) rename examples/C++/DDS/{ContentFilterTopic => ContentFilteredTopicExample}/HelloWorld.idl (100%) rename examples/C++/DDS/{ContentFilterTopic => ContentFilteredTopicExample}/HelloWorldPubSubTypes.cxx (100%) rename examples/C++/DDS/{ContentFilterTopic => ContentFilteredTopicExample}/HelloWorldPubSubTypes.h (100%) rename examples/C++/DDS/{ContentFilterTopic => ContentFilteredTopicExample}/HelloWorldTypeObject.cxx (100%) rename examples/C++/DDS/{ContentFilterTopic => ContentFilteredTopicExample}/HelloWorldTypeObject.h (100%) rename examples/C++/DDS/{ContentFilterTopic => ContentFilteredTopicExample}/MyCustomFilter.hpp (100%) rename examples/C++/DDS/{ContentFilterTopic => ContentFilteredTopicExample}/MyCustomFilterFactory.hpp (100%) diff --git a/examples/C++/DDS/CMakeLists.txt b/examples/C++/DDS/CMakeLists.txt index 7998ad9886c..0614c6b0fb9 100644 --- a/examples/C++/DDS/CMakeLists.txt +++ b/examples/C++/DDS/CMakeLists.txt @@ -18,7 +18,7 @@ add_subdirectory(BasicConfigurationExample) add_subdirectory(Benchmark) add_subdirectory(ClientServerTest) add_subdirectory(Configurability) -add_subdirectory(ContentFilterTopic) +add_subdirectory(ContentFilteredTopicExample) add_subdirectory(CustomListenerExample) add_subdirectory(DeadlineQoSExample) add_subdirectory(DisablePositiveACKs) diff --git a/examples/C++/DDS/ContentFilterTopic/DefaultSQLFilterPublisher.cpp b/examples/C++/DDS/ContentFilterTopic/DefaultSQLFilterPublisher.cpp deleted file mode 100644 index 9f05972c1ba..00000000000 --- a/examples/C++/DDS/ContentFilterTopic/DefaultSQLFilterPublisher.cpp +++ /dev/null @@ -1,185 +0,0 @@ -// Copyright 2022 Proyectos y Sistemas de Mantenimiento SL (eProsima). -// -// 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. - -/** - * @file DefaultSQLFilterPublisher.cpp - * - */ - -#include "DefaultSQLFilterPublisher.hpp" -#include -#include -#include -#include -#include -#include -#include - -#include - -using namespace eprosima::fastdds::dds; - -DefaultSQLFilterPublisher::DefaultSQLFilterPublisher() - : participant_(nullptr) - , publisher_(nullptr) - , topic_(nullptr) - , writer_(nullptr) - , type_(new HelloWorldPubSubType()) -{ -} - -bool DefaultSQLFilterPublisher::init() -{ - hello_.index(0); - hello_.message("HelloWorld"); - DomainParticipantQos pqos; - pqos.name("Participant_pub"); - participant_ = DomainParticipantFactory::get_instance()->create_participant(0, pqos); - - if (participant_ == nullptr) - { - return false; - } - - //REGISTER THE TYPE - type_.register_type(participant_); - - //CREATE THE PUBLISHER - publisher_ = participant_->create_publisher(PUBLISHER_QOS_DEFAULT, nullptr); - - if (publisher_ == nullptr) - { - return false; - } - - topic_ = participant_->create_topic("HelloWorldTopic", "HelloWorld", TOPIC_QOS_DEFAULT); - - if (topic_ == nullptr) - { - return false; - } - - // CREATE THE WRITER - writer_ = publisher_->create_datawriter(topic_, DATAWRITER_QOS_DEFAULT, &listener_); - - if (writer_ == nullptr) - { - return false; - } - return true; -} - -DefaultSQLFilterPublisher::~DefaultSQLFilterPublisher() -{ - if (writer_ != nullptr) - { - publisher_->delete_datawriter(writer_); - } - if (publisher_ != nullptr) - { - participant_->delete_publisher(publisher_); - } - if (topic_ != nullptr) - { - participant_->delete_topic(topic_); - } - DomainParticipantFactory::get_instance()->delete_participant(participant_); -} - -void DefaultSQLFilterPublisher::PubListener::on_publication_matched( - eprosima::fastdds::dds::DataWriter*, - const eprosima::fastdds::dds::PublicationMatchedStatus& info) -{ - if (info.current_count_change == 1) - { - matched_ = info.total_count; - firstConnected_ = true; - std::cout << "Publisher matched." << std::endl; - } - else if (info.current_count_change == -1) - { - matched_ = info.total_count; - std::cout << "Publisher unmatched." << std::endl; - } - else - { - std::cout << info.current_count_change - << " is not a valid value for PublicationMatchedStatus current count change" << std::endl; - } -} - -void DefaultSQLFilterPublisher::runThread( - uint32_t samples, - uint32_t sleep) -{ - if (samples == 0) - { - while (!stop_) - { - if (publish(false)) - { - std::cout << "Message: " << hello_.message() << " with index: " << hello_.index() - << " SENT" << std::endl; - } - std::this_thread::sleep_for(std::chrono::milliseconds(sleep)); - } - } - else - { - for (uint32_t i = 0; i < samples; ++i) - { - if (!publish()) - { - --i; - } - else - { - std::cout << "Message: " << hello_.message() << " with index: " << hello_.index() - << " SENT" << std::endl; - } - std::this_thread::sleep_for(std::chrono::milliseconds(sleep)); - } - } -} - -void DefaultSQLFilterPublisher::run( - uint32_t samples, - uint32_t sleep) -{ - stop_ = false; - std::thread thread(&DefaultSQLFilterPublisher::runThread, this, samples, sleep); - if (samples == 0) - { - std::cout << "Publisher running. Please press enter to stop the Publisher at any time." << std::endl; - std::cin.ignore(); - stop_ = true; - } - else - { - std::cout << "Publisher running " << samples << " samples." << std::endl; - } - thread.join(); -} - -bool DefaultSQLFilterPublisher::publish( - bool waitForListener) -{ - if (listener_.firstConnected_ || !waitForListener || listener_.matched_ > 0) - { - hello_.index(hello_.index() + 1); - writer_->write(&hello_); - return true; - } - return false; -} diff --git a/examples/C++/DDS/ContentFilterTopic/DefaultSQLFilterPublisher.hpp b/examples/C++/DDS/ContentFilterTopic/DefaultSQLFilterPublisher.hpp deleted file mode 100644 index 2f108ba49a3..00000000000 --- a/examples/C++/DDS/ContentFilterTopic/DefaultSQLFilterPublisher.hpp +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright 2022 Proyectos y Sistemas de Mantenimiento SL (eProsima). -// -// 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. - -/** - * @file DefaultSQLFilterPublisher.hpp - * - */ - -#ifndef _DEFAULTSQLFILTERPUBLISHER_H_ -#define _DEFAULTSQLFILTERPUBLISHER_H_ - -#include "HelloWorldPubSubTypes.h" - -#include -#include -#include - -class DefaultSQLFilterPublisher -{ -public: - - DefaultSQLFilterPublisher(); - - virtual ~DefaultSQLFilterPublisher(); - - //!Initialize - bool init(); - - //!Publish a sample - bool publish( - bool waitForListener = true); - - //!Run for number samples - void run( - uint32_t number, - uint32_t sleep); - -private: - - HelloWorld hello_; - - eprosima::fastdds::dds::DomainParticipant* participant_; - - eprosima::fastdds::dds::Publisher* publisher_; - - eprosima::fastdds::dds::Topic* topic_; - - eprosima::fastdds::dds::DataWriter* writer_; - - bool stop_; - - class PubListener : public eprosima::fastdds::dds::DataWriterListener - { - public: - - PubListener() - : matched_(0) - , firstConnected_(false) - { - } - - ~PubListener() override - { - } - - void on_publication_matched( - eprosima::fastdds::dds::DataWriter* writer, - const eprosima::fastdds::dds::PublicationMatchedStatus& info) override; - - int matched_; - - bool firstConnected_; - } - listener_; - - void runThread( - uint32_t number, - uint32_t sleep); - - eprosima::fastdds::dds::TypeSupport type_; -}; - - - -#endif // _DEFAULTSQLFILTERPUBLISHER_H_ diff --git a/examples/C++/DDS/ContentFilterTopic/DefaultSQLFilterSubscriber.cpp b/examples/C++/DDS/ContentFilterTopic/DefaultSQLFilterSubscriber.cpp deleted file mode 100644 index 9a2682572e0..00000000000 --- a/examples/C++/DDS/ContentFilterTopic/DefaultSQLFilterSubscriber.cpp +++ /dev/null @@ -1,162 +0,0 @@ -// Copyright 2022 Proyectos y Sistemas de Mantenimiento SL (eProsima). -// -// 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. - -/** - * @file DefaultSQLFilterSubscriber.cpp - * - */ - -#include "DefaultSQLFilterSubscriber.hpp" -#include -#include -#include -#include -#include -#include -#include - -using namespace eprosima::fastdds::dds; - -bool DefaultSQLFilterSubscriber::init() -{ - DomainParticipantQos pqos; - pqos.name("Participant_sub"); - participant_ = DomainParticipantFactory::get_instance()->create_participant(0, pqos); - - if (participant_ == nullptr) - { - return false; - } - - //Register the type - type_.register_type(participant_); - - //CREATE THE SUBSCRIBER - subscriber_ = participant_->create_subscriber(SUBSCRIBER_QOS_DEFAULT, nullptr); - - if (subscriber_ == nullptr) - { - return false; - } - - //Create the topic - topic_ = participant_->create_topic( - "HelloWorldTopic", - "HelloWorld", - TOPIC_QOS_DEFAULT); - - if (topic_ == nullptr) - { - return false; - } - - // Create a ContentFilteredTopic using an expression with no parameters - std::string expression = "index < %0 or index > %1"; - std::vector parameters; - parameters.push_back("3"); - parameters.push_back("5"); - filter_topic_ = - participant_->create_contentfilteredtopic("HelloWorldFilteredTopic1", topic_, expression, parameters); - - if (nullptr == filter_topic_) - { - // Error - return false; - } - - // CREATE THE READER - DataReaderQos rqos = DATAREADER_QOS_DEFAULT; - rqos.reliability().kind = RELIABLE_RELIABILITY_QOS; - reader_ = subscriber_->create_datareader(filter_topic_, rqos, &listener_); - - if (reader_ == nullptr) - { - return false; - } - - return true; -} - -DefaultSQLFilterSubscriber::~DefaultSQLFilterSubscriber() -{ - if (reader_ != nullptr) - { - subscriber_->delete_datareader(reader_); - } - if (nullptr != filter_topic_) - { - participant_->delete_contentfilteredtopic(filter_topic_); - } - if (topic_ != nullptr) - { - participant_->delete_topic(topic_); - } - if (subscriber_ != nullptr) - { - participant_->delete_subscriber(subscriber_); - } - DomainParticipantFactory::get_instance()->delete_participant(participant_); -} - -void DefaultSQLFilterSubscriber::SubListener::on_subscription_matched( - DataReader*, - const SubscriptionMatchedStatus& info) -{ - if (info.current_count_change == 1) - { - matched_ = info.total_count; - std::cout << "Subscriber matched." << std::endl; - } - else if (info.current_count_change == -1) - { - matched_ = info.total_count; - std::cout << "Subscriber unmatched." << std::endl; - } - else - { - std::cout << info.current_count_change - << " is not a valid value for SubscriptionMatchedStatus current count change" << std::endl; - } -} - -void DefaultSQLFilterSubscriber::SubListener::on_data_available( - DataReader* reader) -{ - SampleInfo info; - if (reader->take_next_sample(&hello_, &info) == ReturnCode_t::RETCODE_OK) - { - if (info.instance_state == ALIVE_INSTANCE_STATE) - { - samples_++; - // Print your structure data here. - std::cout << "Message " << hello_.message() << " " << hello_.index() << " RECEIVED" << std::endl; - } - } -} - -void DefaultSQLFilterSubscriber::run() -{ - std::cout << "Subscriber running. Please press enter to stop the Subscriber" << std::endl; - std::cin.ignore(); -} - -void DefaultSQLFilterSubscriber::run( - uint32_t number) -{ - std::cout << "Subscriber running until " << number << "samples have been received" << std::endl; - while (number > listener_.samples_) - { - std::this_thread::sleep_for(std::chrono::milliseconds(500)); - } -} diff --git a/examples/C++/DDS/ContentFilterTopic/DefaultSQLFilterSubscriber.hpp b/examples/C++/DDS/ContentFilterTopic/DefaultSQLFilterSubscriber.hpp deleted file mode 100644 index ddff178fb6f..00000000000 --- a/examples/C++/DDS/ContentFilterTopic/DefaultSQLFilterSubscriber.hpp +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2021 Proyectos y Sistemas de Mantenimiento SL (eProsima). -// -// 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. - -/** - * @file DefaultSQLFilterSubscriber.hpp - * - */ - -#ifndef _DEFAULTSQLFILTERSUBSCRIBER_HPP_ -#define _DEFAULTSQLFILTERSUBSCRIBER_HPP_ - -#include "HelloWorldPubSubTypes.h" - -#include -#include -#include -#include - -class DefaultSQLFilterSubscriber -{ -public: - - DefaultSQLFilterSubscriber() = default; - - virtual ~DefaultSQLFilterSubscriber(); - - //!Initialize the subscriber - bool init(); - - //!RUN the subscriber - void run(); - - //!Run the subscriber until number samples have been received. - void run( - uint32_t number); - -private: - - eprosima::fastdds::dds::DomainParticipant* participant_ = nullptr; - - eprosima::fastdds::dds::Subscriber* subscriber_ = nullptr; - - eprosima::fastdds::dds::Topic* topic_ = nullptr; - - eprosima::fastdds::dds::ContentFilteredTopic* filter_topic_ = nullptr; - - eprosima::fastdds::dds::DataReader* reader_ = nullptr; - - eprosima::fastdds::dds::TypeSupport type_ = eprosima::fastdds::dds::TypeSupport(new HelloWorldPubSubType()); - - class SubListener : public eprosima::fastdds::dds::DataReaderListener - { - public: - - ~SubListener() override - { - } - - void on_data_available( - eprosima::fastdds::dds::DataReader* reader) override; - - void on_subscription_matched( - eprosima::fastdds::dds::DataReader* reader, - const eprosima::fastdds::dds::SubscriptionMatchedStatus& info) override; - - HelloWorld hello_; - - int matched_ = 0; - - uint32_t samples_ = 0; - } - listener_; -}; - -#endif // _DEFAULTSQLFILTERSUBSCRIBER_HPP_ diff --git a/examples/C++/DDS/ContentFilterTopic/DefaultSQLFilter_main.cpp b/examples/C++/DDS/ContentFilterTopic/DefaultSQLFilter_main.cpp deleted file mode 100644 index 9c9c7657352..00000000000 --- a/examples/C++/DDS/ContentFilterTopic/DefaultSQLFilter_main.cpp +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2022 Proyectos y Sistemas de Mantenimiento SL (eProsima). -// -// 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. - -/** - * @file DefaultSQLFilter_main.cpp - * - */ - -#include "DefaultSQLFilterPublisher.hpp" -#include "DefaultSQLFilterSubscriber.hpp" - -#include - -#include - -using eprosima::fastdds::dds::Log; - -int main( - int argc, - char** argv) -{ - std::cout << "Starting " << std::endl; - int type = 1; - int count = 10; - int sleep = 100; - if (argc > 1) - { - if (strcmp(argv[1], "publisher") == 0) - { - type = 1; - if (argc >= 3) - { - count = atoi(argv[2]); - if (argc == 4) - { - sleep = atoi(argv[3]); - } - } - } - else if (strcmp(argv[1], "subscriber") == 0) - { - type = 2; - } - } - else - { - std::cout << "publisher OR subscriber argument needed" << std::endl; - Log::Reset(); - return 0; - } - - switch (type) - { - case 1: - { - DefaultSQLFilterPublisher mypub; - if (mypub.init()) - { - mypub.run(static_cast(count), static_cast(sleep)); - } - break; - } - case 2: - { - DefaultSQLFilterSubscriber mysub; - if (mysub.init()) - { - mysub.run(); - } - break; - } - } - Log::Reset(); - return 0; -} diff --git a/examples/C++/DDS/ContentFilterTopic/CMakeLists.txt b/examples/C++/DDS/ContentFilteredTopicExample/CMakeLists.txt similarity index 52% rename from examples/C++/DDS/ContentFilterTopic/CMakeLists.txt rename to examples/C++/DDS/ContentFilteredTopicExample/CMakeLists.txt index 7e195f7f276..d556606111e 100644 --- a/examples/C++/DDS/ContentFilterTopic/CMakeLists.txt +++ b/examples/C++/DDS/ContentFilteredTopicExample/CMakeLists.txt @@ -28,38 +28,20 @@ endif() message(STATUS "Configuring ContentFilterTopic examples...") set(CFT_COMMON_SOURCES + ContentFilteredTopicExample_main.cpp + ContentFilteredTopicExamplePublisher.cpp + ContentFilteredTopicExampleSubscriber.cpp HelloWorld.cxx HelloWorldPubSubTypes.cxx HelloWorldTypeObject.cxx ) -set(CFT_DSF_SOURCES - DefaultSQLFilterPublisher.cpp - DefaultSQLFilterSubscriber.cpp - DefaultSQLFilter_main.cpp) - -set(CFT_CF_SOURCES - CustomFilterPublisher.cpp - CustomFilterSubscriber.cpp - CustomFilter_main.cpp) - - -add_executable(DefaultSQLFilter ${CFT_COMMON_SOURCES} ${CFT_DSF_SOURCES}) -target_compile_definitions(DefaultSQLFilter PRIVATE - $<$>,$>:__DEBUG> - $<$:__INTERNALDEBUG> # Internal debug activated. -) -target_compile_features(DefaultSQLFilter PRIVATE cxx_std_11) -target_link_libraries(DefaultSQLFilter fastrtps fastcdr) -install(TARGETS DefaultSQLFilter - RUNTIME DESTINATION examples/C++/DDS/ContentFilterTopic/${BIN_INSTALL_DIR}) - -add_executable(CustomFilter ${CFT_COMMON_SOURCES} ${CFT_CF_SOURCES}) -target_compile_definitions(CustomFilter PRIVATE +add_executable(DDSContentFilteredTopicExample ${CFT_COMMON_SOURCES}) +target_compile_definitions(DDSContentFilteredTopicExample PRIVATE $<$>,$>:__DEBUG> $<$:__INTERNALDEBUG> # Internal debug activated. ) -target_compile_features(CustomFilter PRIVATE cxx_std_11) -target_link_libraries(CustomFilter fastrtps fastcdr) -install(TARGETS CustomFilter - RUNTIME DESTINATION examples/C++/DDS/ContentFilterTopic/${BIN_INSTALL_DIR}) +target_compile_features(DDSContentFilteredTopicExample PRIVATE cxx_std_11) +target_link_libraries(DDSContentFilteredTopicExample fastrtps fastcdr) +install(TARGETS DDSContentFilteredTopicExample + RUNTIME DESTINATION examples/C++/DDS/ContentFilteredTopic/${BIN_INSTALL_DIR}) diff --git a/examples/C++/DDS/ContentFilterTopic/CustomFilterPublisher.cpp b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.cpp similarity index 98% rename from examples/C++/DDS/ContentFilterTopic/CustomFilterPublisher.cpp rename to examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.cpp index 1ddb004a166..4753b914d89 100644 --- a/examples/C++/DDS/ContentFilterTopic/CustomFilterPublisher.cpp +++ b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.cpp @@ -17,7 +17,7 @@ * */ -#include "CustomFilterPublisher.hpp" +#include "ContentFilteredTopicExamplePublisher.hpp" #include #include #include diff --git a/examples/C++/DDS/ContentFilterTopic/CustomFilterPublisher.hpp b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.hpp similarity index 97% rename from examples/C++/DDS/ContentFilterTopic/CustomFilterPublisher.hpp rename to examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.hpp index 7e0a2ce0e26..8c870d98e1b 100644 --- a/examples/C++/DDS/ContentFilterTopic/CustomFilterPublisher.hpp +++ b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.hpp @@ -70,9 +70,7 @@ class CustomFilterPublisher { } - ~PubListener() override - { - } + ~PubListener() override = default; void on_publication_matched( eprosima::fastdds::dds::DataWriter* writer, diff --git a/examples/C++/DDS/ContentFilterTopic/CustomFilterSubscriber.cpp b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.cpp similarity index 98% rename from examples/C++/DDS/ContentFilterTopic/CustomFilterSubscriber.cpp rename to examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.cpp index 10b47a6425b..21b973a9f71 100644 --- a/examples/C++/DDS/ContentFilterTopic/CustomFilterSubscriber.cpp +++ b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.cpp @@ -17,7 +17,7 @@ * */ -#include "CustomFilterSubscriber.hpp" +#include "ContentFilteredTopicExampleSubscriber.hpp" #include #include #include diff --git a/examples/C++/DDS/ContentFilterTopic/CustomFilterSubscriber.hpp b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.hpp similarity index 100% rename from examples/C++/DDS/ContentFilterTopic/CustomFilterSubscriber.hpp rename to examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.hpp diff --git a/examples/C++/DDS/ContentFilterTopic/CustomFilter_main.cpp b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExample_main.cpp similarity index 95% rename from examples/C++/DDS/ContentFilterTopic/CustomFilter_main.cpp rename to examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExample_main.cpp index 5f01443fc37..605cfe3c3c6 100644 --- a/examples/C++/DDS/ContentFilterTopic/CustomFilter_main.cpp +++ b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExample_main.cpp @@ -17,8 +17,8 @@ * */ -#include "CustomFilterPublisher.hpp" -#include "CustomFilterSubscriber.hpp" +#include "ContentFilteredTopicExamplePublisher.hpp" +#include "ContentFilteredTopicExampleSubscriber.hpp" #include diff --git a/examples/C++/DDS/ContentFilterTopic/HelloWorld.cxx b/examples/C++/DDS/ContentFilteredTopicExample/HelloWorld.cxx similarity index 100% rename from examples/C++/DDS/ContentFilterTopic/HelloWorld.cxx rename to examples/C++/DDS/ContentFilteredTopicExample/HelloWorld.cxx diff --git a/examples/C++/DDS/ContentFilterTopic/HelloWorld.h b/examples/C++/DDS/ContentFilteredTopicExample/HelloWorld.h similarity index 100% rename from examples/C++/DDS/ContentFilterTopic/HelloWorld.h rename to examples/C++/DDS/ContentFilteredTopicExample/HelloWorld.h diff --git a/examples/C++/DDS/ContentFilterTopic/HelloWorld.idl b/examples/C++/DDS/ContentFilteredTopicExample/HelloWorld.idl similarity index 100% rename from examples/C++/DDS/ContentFilterTopic/HelloWorld.idl rename to examples/C++/DDS/ContentFilteredTopicExample/HelloWorld.idl diff --git a/examples/C++/DDS/ContentFilterTopic/HelloWorldPubSubTypes.cxx b/examples/C++/DDS/ContentFilteredTopicExample/HelloWorldPubSubTypes.cxx similarity index 100% rename from examples/C++/DDS/ContentFilterTopic/HelloWorldPubSubTypes.cxx rename to examples/C++/DDS/ContentFilteredTopicExample/HelloWorldPubSubTypes.cxx diff --git a/examples/C++/DDS/ContentFilterTopic/HelloWorldPubSubTypes.h b/examples/C++/DDS/ContentFilteredTopicExample/HelloWorldPubSubTypes.h similarity index 100% rename from examples/C++/DDS/ContentFilterTopic/HelloWorldPubSubTypes.h rename to examples/C++/DDS/ContentFilteredTopicExample/HelloWorldPubSubTypes.h diff --git a/examples/C++/DDS/ContentFilterTopic/HelloWorldTypeObject.cxx b/examples/C++/DDS/ContentFilteredTopicExample/HelloWorldTypeObject.cxx similarity index 100% rename from examples/C++/DDS/ContentFilterTopic/HelloWorldTypeObject.cxx rename to examples/C++/DDS/ContentFilteredTopicExample/HelloWorldTypeObject.cxx diff --git a/examples/C++/DDS/ContentFilterTopic/HelloWorldTypeObject.h b/examples/C++/DDS/ContentFilteredTopicExample/HelloWorldTypeObject.h similarity index 100% rename from examples/C++/DDS/ContentFilterTopic/HelloWorldTypeObject.h rename to examples/C++/DDS/ContentFilteredTopicExample/HelloWorldTypeObject.h diff --git a/examples/C++/DDS/ContentFilterTopic/MyCustomFilter.hpp b/examples/C++/DDS/ContentFilteredTopicExample/MyCustomFilter.hpp similarity index 100% rename from examples/C++/DDS/ContentFilterTopic/MyCustomFilter.hpp rename to examples/C++/DDS/ContentFilteredTopicExample/MyCustomFilter.hpp diff --git a/examples/C++/DDS/ContentFilterTopic/MyCustomFilterFactory.hpp b/examples/C++/DDS/ContentFilteredTopicExample/MyCustomFilterFactory.hpp similarity index 100% rename from examples/C++/DDS/ContentFilterTopic/MyCustomFilterFactory.hpp rename to examples/C++/DDS/ContentFilteredTopicExample/MyCustomFilterFactory.hpp From 41716873ec304c25c0d36e3eb6749830a29c4249 Mon Sep 17 00:00:00 2001 From: JLBuenoLopez-eProsima Date: Wed, 6 Apr 2022 13:04:31 +0200 Subject: [PATCH 04/17] Refs #14220: infrastructure to run either the default or the custom filter. Default filter expression has been modified to filter different messages than the custom filter Signed-off-by: JLBuenoLopez-eProsima --- .../ContentFilteredTopicExampleSubscriber.cpp | 43 +++++++++++++------ .../ContentFilteredTopicExampleSubscriber.hpp | 12 +++++- .../ContentFilteredTopicExample_main.cpp | 10 ++++- 3 files changed, 48 insertions(+), 17 deletions(-) diff --git a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.cpp b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.cpp index 21b973a9f71..f5cfc7666ef 100644 --- a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.cpp +++ b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.cpp @@ -28,7 +28,8 @@ using namespace eprosima::fastdds::dds; -bool CustomFilterSubscriber::init() +bool CustomFilterSubscriber::init( + bool custom_filter) { DomainParticipantQos pqos; pqos.name("Participant_sub"); @@ -39,12 +40,15 @@ bool CustomFilterSubscriber::init() return false; } - // Register the filter factory - if (ReturnCode_t::RETCODE_OK != - participant_->register_content_filter_factory("MY_CUSTOM_FILTER", &filter_factory)) + if (custom_filter) { - // Error - return false; + // Register the filter factory + if (ReturnCode_t::RETCODE_OK != + participant_->register_content_filter_factory("MY_CUSTOM_FILTER", &filter_factory)) + { + // Error + return false; + } } //Register the type @@ -69,14 +73,27 @@ bool CustomFilterSubscriber::init() return false; } - // Create a ContentFilteredTopic using an expression with no parameters - std::string expression = " "; + // Create ContentFilteredTopic + std::string expression; std::vector parameters; - parameters.push_back("3"); - parameters.push_back("5"); - filter_topic_ = - participant_->create_contentfilteredtopic("HelloWorldFilteredTopic1", topic_, expression, parameters, - "MY_CUSTOM_FILTER"); + if (custom_filter) + { + // Custom filter: reject samples where index > parameters[0] and index < parameters[1]. + expression = " "; + parameters.push_back("3"); + parameters.push_back("5"); + filter_topic_ = + participant_->create_contentfilteredtopic("HelloWorldFilteredTopic1", topic_, expression, parameters, + "MY_CUSTOM_FILTER"); + } + else + { + expression = "index between %0 and %1"; + parameters.push_back("5"); + parameters.push_back("9"); + filter_topic_ = + participant_->create_contentfilteredtopic("HelloWorldFilteredTopic1", topic_, expression, parameters); + } if (nullptr == filter_topic_) { diff --git a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.hpp b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.hpp index a0d104abee1..dbbc8511de8 100644 --- a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.hpp +++ b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.hpp @@ -36,8 +36,16 @@ class CustomFilterSubscriber virtual ~CustomFilterSubscriber(); - //!Initialize the subscriber - bool init(); + /** + * @brief Initialize the subscriber + * + * @param custom_filter Whether the default SQL filter or the custom defined filter is used. + * By default the SQL filter is used. + * @return true if correctly initialized. + * @return false otherwise. + */ + bool init( + bool custom_filter = false); //!RUN the subscriber void run(); diff --git a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExample_main.cpp b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExample_main.cpp index 605cfe3c3c6..c3bc2c863b9 100644 --- a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExample_main.cpp +++ b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExample_main.cpp @@ -34,6 +34,7 @@ int main( int type = 1; int count = 10; int sleep = 100; + bool custom_filter = false; if (argc > 1) { if (strcmp(argv[1], "publisher") == 0) @@ -48,10 +49,15 @@ int main( } } } - else if (strcmp(argv[1], "subscriber") == 0) + else if (strcmp(argv[1], "default_subscriber") == 0) { type = 2; } + else if (strcmp(argv[1], "custom_subscriber") == 0) + { + type = 2; + custom_filter = true; + } } else { @@ -74,7 +80,7 @@ int main( case 2: { CustomFilterSubscriber mysub; - if (mysub.init()) + if (mysub.init(custom_filter)) { mysub.run(); } From 62eb6f191fae45eba9135c0d2f87fc88d5d80ff7 Mon Sep 17 00:00:00 2001 From: JLBuenoLopez-eProsima Date: Wed, 6 Apr 2022 13:15:35 +0200 Subject: [PATCH 05/17] Refs #14220: fix installation folder Signed-off-by: JLBuenoLopez-eProsima --- examples/C++/DDS/ContentFilteredTopicExample/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/C++/DDS/ContentFilteredTopicExample/CMakeLists.txt b/examples/C++/DDS/ContentFilteredTopicExample/CMakeLists.txt index d556606111e..d360d423004 100644 --- a/examples/C++/DDS/ContentFilteredTopicExample/CMakeLists.txt +++ b/examples/C++/DDS/ContentFilteredTopicExample/CMakeLists.txt @@ -44,4 +44,4 @@ target_compile_definitions(DDSContentFilteredTopicExample PRIVATE target_compile_features(DDSContentFilteredTopicExample PRIVATE cxx_std_11) target_link_libraries(DDSContentFilteredTopicExample fastrtps fastcdr) install(TARGETS DDSContentFilteredTopicExample - RUNTIME DESTINATION examples/C++/DDS/ContentFilteredTopic/${BIN_INSTALL_DIR}) + RUNTIME DESTINATION examples/C++/DDS/ContentFilteredTopicExample/${BIN_INSTALL_DIR}) From 892cb1a8e69fd1f9a5ae42760b99edd1606f745b Mon Sep 17 00:00:00 2001 From: JLBuenoLopez-eProsima Date: Wed, 6 Apr 2022 13:15:54 +0200 Subject: [PATCH 06/17] Refs #14220: add example README Signed-off-by: JLBuenoLopez-eProsima --- .../DDS/ContentFilteredTopicExample/README.md | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 examples/C++/DDS/ContentFilteredTopicExample/README.md diff --git a/examples/C++/DDS/ContentFilteredTopicExample/README.md b/examples/C++/DDS/ContentFilteredTopicExample/README.md new file mode 100644 index 00000000000..ccc1f5ebc65 --- /dev/null +++ b/examples/C++/DDS/ContentFilteredTopicExample/README.md @@ -0,0 +1,21 @@ +# Content Filtered Topic Example + +This example extends the HelloWorld example to show how to use Content Filtered Topics. +The example includes the use of two different Filter Factories. +On the one hand the default SQL filter and on the other hand a custom filter defined in the example. + +## Execution instructions + +To launch this example open three different consoles: + +In the first one launch the Subscriber using the default SQL filter: ./DDSContentFilteredTopicExample default_subscriber +In the second one launch the Subscriber using the custom filter: ./DDSContentFilteredTopicExample custom_subscriber +Finally, in the third terminal launch the Publisher: ./DDSContentFilteredTopicExample publisher + +The default Subscriber should received only the samples between indexes 5 and 9. +Custom Subscriber should received samples which index is lower than 3 and greater than 5. + +## Arguments + +First argument is mandatory and it should be one of the following values: `publisher`, `default_subscriber` and `custom_subscriber`. +The `publisher` can be launched specifying the number of samples to be sent (10 by default) and the sleep between samples in [ms] (by default 100 ms) in that order. \ No newline at end of file From 6cb68436dd8af900cd1fd25abc0bc47ada262939 Mon Sep 17 00:00:00 2001 From: JLBuenoLopez-eProsima Date: Wed, 6 Apr 2022 15:17:00 +0200 Subject: [PATCH 07/17] Refs #14220: apply review suggestions Signed-off-by: JLBuenoLopez-eProsima --- .../ContentFilteredTopicExamplePublisher.cpp | 73 +++++++------------ .../ContentFilteredTopicExamplePublisher.hpp | 67 +++++++---------- .../ContentFilteredTopicExampleSubscriber.cpp | 70 ++++++------------ .../ContentFilteredTopicExampleSubscriber.hpp | 59 +++++++-------- .../ContentFilteredTopicExample_main.cpp | 4 +- .../MyCustomFilter.hpp | 9 +-- .../MyCustomFilterFactory.hpp | 12 +-- .../DDS/ContentFilteredTopicExample/README.md | 3 +- 8 files changed, 118 insertions(+), 179 deletions(-) diff --git a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.cpp b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.cpp index 4753b914d89..f9eb6141405 100644 --- a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.cpp +++ b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.cpp @@ -13,33 +13,25 @@ // limitations under the License. /** - * @file CustomFilterPublisher.cpp + * @file ContentFilteredTopicExamplePublisher.cpp * */ #include "ContentFilteredTopicExamplePublisher.hpp" -#include -#include + +#include + +#include #include -#include -#include +#include #include +#include #include - -#include +#include using namespace eprosima::fastdds::dds; -CustomFilterPublisher::CustomFilterPublisher() - : participant_(nullptr) - , publisher_(nullptr) - , topic_(nullptr) - , writer_(nullptr) - , type_(new HelloWorldPubSubType()) -{ -} - -bool CustomFilterPublisher::init() +bool ContentFilteredTopicExamplePublisher::init() { hello_.index(0); hello_.message("HelloWorld"); @@ -47,7 +39,7 @@ bool CustomFilterPublisher::init() pqos.name("Participant_pub"); participant_ = DomainParticipantFactory::get_instance()->create_participant(0, pqos); - if (participant_ == nullptr) + if (nullptr == participant_) { return false; } @@ -58,58 +50,47 @@ bool CustomFilterPublisher::init() //CREATE THE PUBLISHER publisher_ = participant_->create_publisher(PUBLISHER_QOS_DEFAULT, nullptr); - if (publisher_ == nullptr) + if (nullptr == publisher_) { return false; } - topic_ = participant_->create_topic("HelloWorldTopic", "HelloWorld", TOPIC_QOS_DEFAULT); + topic_ = participant_->create_topic("HelloWorldTopic", type_->getName(), TOPIC_QOS_DEFAULT); - if (topic_ == nullptr) + if (nullptr == topic_) { return false; } // CREATE THE WRITER - writer_ = publisher_->create_datawriter(topic_, DATAWRITER_QOS_DEFAULT, &listener_); + writer_ = publisher_->create_datawriter(topic_, DATAWRITER_QOS_DEFAULT, this); - if (writer_ == nullptr) + if (nullptr == writer_) { return false; } return true; } -CustomFilterPublisher::~CustomFilterPublisher() +ContentFilteredTopicExamplePublisher::~ContentFilteredTopicExamplePublisher() { - if (writer_ != nullptr) - { - publisher_->delete_datawriter(writer_); - } - if (publisher_ != nullptr) - { - participant_->delete_publisher(publisher_); - } - if (topic_ != nullptr) - { - participant_->delete_topic(topic_); - } + participant_->delete_contained_entities(); DomainParticipantFactory::get_instance()->delete_participant(participant_); } -void CustomFilterPublisher::PubListener::on_publication_matched( - eprosima::fastdds::dds::DataWriter*, - const eprosima::fastdds::dds::PublicationMatchedStatus& info) +void ContentFilteredTopicExamplePublisher::on_publication_matched( + DataWriter*, + const PublicationMatchedStatus& info) { if (info.current_count_change == 1) { - matched_ = info.total_count; + matched_ = info.current_count; firstConnected_ = true; std::cout << "Publisher matched." << std::endl; } else if (info.current_count_change == -1) { - matched_ = info.total_count; + matched_ = info.current_count; std::cout << "Publisher unmatched." << std::endl; } else @@ -119,7 +100,7 @@ void CustomFilterPublisher::PubListener::on_publication_matched( } } -void CustomFilterPublisher::runThread( +void ContentFilteredTopicExamplePublisher::runThread( uint32_t samples, uint32_t sleep) { @@ -153,12 +134,12 @@ void CustomFilterPublisher::runThread( } } -void CustomFilterPublisher::run( +void ContentFilteredTopicExamplePublisher::run( uint32_t samples, uint32_t sleep) { stop_ = false; - std::thread thread(&CustomFilterPublisher::runThread, this, samples, sleep); + std::thread thread(&ContentFilteredTopicExamplePublisher::runThread, this, samples, sleep); if (samples == 0) { std::cout << "Publisher running. Please press enter to stop the Publisher at any time." << std::endl; @@ -172,10 +153,10 @@ void CustomFilterPublisher::run( thread.join(); } -bool CustomFilterPublisher::publish( +bool ContentFilteredTopicExamplePublisher::publish( bool waitForListener) { - if (listener_.firstConnected_ || !waitForListener || listener_.matched_ > 0) + if (firstConnected_ || !waitForListener || matched_ > 0) { hello_.index(hello_.index() + 1); writer_->write(&hello_); diff --git a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.hpp b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.hpp index 8c870d98e1b..6ae231c03a0 100644 --- a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.hpp +++ b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.hpp @@ -13,35 +13,39 @@ // limitations under the License. /** - * @file CustomFilterPublisher.hpp + * @file ContentFilteredTopicExamplePublisher.hpp * */ -#ifndef _DEFAULTSQLFILTERPUBLISHER_H_ -#define _DEFAULTSQLFILTERPUBLISHER_H_ - -#include "HelloWorldPubSubTypes.h" +#ifndef _CONTENTFILTEREDTOPICEXAMPLEPUBLISHER_H_ +#define _CONTENTFILTEREDTOPICEXAMPLEPUBLISHER_H_ +#include +#include #include +#include +#include +#include #include -#include -class CustomFilterPublisher +#include "HelloWorldPubSubTypes.h" + +class ContentFilteredTopicExamplePublisher : public eprosima::fastdds::dds::DataWriterListener { public: - CustomFilterPublisher(); + ContentFilteredTopicExamplePublisher() = default; - virtual ~CustomFilterPublisher(); + virtual ~ContentFilteredTopicExamplePublisher(); - //!Initialize + //! Initialize bool init(); - //!Publish a sample + //! Publish a sample bool publish( bool waitForListener = true); - //!Run for number samples + //! Run for number samples void run( uint32_t number, uint32_t sleep); @@ -50,45 +54,30 @@ class CustomFilterPublisher HelloWorld hello_; - eprosima::fastdds::dds::DomainParticipant* participant_; + eprosima::fastdds::dds::DomainParticipant* participant_ = nullptr; - eprosima::fastdds::dds::Publisher* publisher_; + eprosima::fastdds::dds::Publisher* publisher_ = nullptr; - eprosima::fastdds::dds::Topic* topic_; + eprosima::fastdds::dds::Topic* topic_ = nullptr; - eprosima::fastdds::dds::DataWriter* writer_; + eprosima::fastdds::dds::DataWriter* writer_ = nullptr; - bool stop_; - - class PubListener : public eprosima::fastdds::dds::DataWriterListener - { - public: - - PubListener() - : matched_(0) - , firstConnected_(false) - { - } + eprosima::fastdds::dds::TypeSupport type_ = eprosima::fastdds::dds::TypeSupport(new HelloWorldPubSubType()); - ~PubListener() override = default; + bool stop_; - void on_publication_matched( - eprosima::fastdds::dds::DataWriter* writer, - const eprosima::fastdds::dds::PublicationMatchedStatus& info) override; + int matched_; - int matched_; + bool firstConnected_; - bool firstConnected_; - } - listener_; + void on_publication_matched( + eprosima::fastdds::dds::DataWriter* writer, + const eprosima::fastdds::dds::PublicationMatchedStatus& info) override; void runThread( uint32_t number, uint32_t sleep); - eprosima::fastdds::dds::TypeSupport type_; }; - - -#endif // _DEFAULTSQLFILTERPUBLISHER_H_ +#endif // _CONTENTFILTEREDTOPICEXAMPLEPUBLISHER_H_ diff --git a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.cpp b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.cpp index f5cfc7666ef..3d1f153e6f9 100644 --- a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.cpp +++ b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.cpp @@ -13,29 +13,30 @@ // limitations under the License. /** - * @file CustomFilterSubscriber.cpp + * @file ContentFilteredTopicExampleSubscriber.cpp * */ #include "ContentFilteredTopicExampleSubscriber.hpp" -#include -#include + +#include #include +#include #include #include -#include #include +#include using namespace eprosima::fastdds::dds; -bool CustomFilterSubscriber::init( +bool ContentFilteredTopicExampleSubscriber::init( bool custom_filter) { DomainParticipantQos pqos; pqos.name("Participant_sub"); participant_ = DomainParticipantFactory::get_instance()->create_participant(0, pqos); - if (participant_ == nullptr) + if (nullptr == participant_) { return false; } @@ -57,18 +58,15 @@ bool CustomFilterSubscriber::init( //CREATE THE SUBSCRIBER subscriber_ = participant_->create_subscriber(SUBSCRIBER_QOS_DEFAULT, nullptr); - if (subscriber_ == nullptr) + if (nullptr == subscriber_) { return false; } //Create the topic - topic_ = participant_->create_topic( - "HelloWorldTopic", - "HelloWorld", - TOPIC_QOS_DEFAULT); + topic_ = participant_->create_topic("HelloWorldTopic", type_->getName(), TOPIC_QOS_DEFAULT); - if (topic_ == nullptr) + if (nullptr == topic_) { return false; } @@ -104,9 +102,10 @@ bool CustomFilterSubscriber::init( // CREATE THE READER DataReaderQos rqos = DATAREADER_QOS_DEFAULT; rqos.reliability().kind = RELIABLE_RELIABILITY_QOS; - reader_ = subscriber_->create_datareader(filter_topic_, rqos, &listener_); + rqos.durability().kind = TRANSIENT_LOCAL_DURABILITY_QOS; + reader_ = subscriber_->create_datareader(filter_topic_, rqos, this); - if (reader_ == nullptr) + if (nullptr == reader_) { return false; } @@ -114,39 +113,24 @@ bool CustomFilterSubscriber::init( return true; } -CustomFilterSubscriber::~CustomFilterSubscriber() +ContentFilteredTopicExampleSubscriber::~ContentFilteredTopicExampleSubscriber() { - if (reader_ != nullptr) - { - subscriber_->delete_datareader(reader_); - } - if (nullptr != filter_topic_) - { - participant_->delete_contentfilteredtopic(filter_topic_); - } - if (topic_ != nullptr) - { - participant_->delete_topic(topic_); - } - if (subscriber_ != nullptr) - { - participant_->delete_subscriber(subscriber_); - } + participant_->delete_contained_entities(); DomainParticipantFactory::get_instance()->delete_participant(participant_); } -void CustomFilterSubscriber::SubListener::on_subscription_matched( +void ContentFilteredTopicExampleSubscriber::on_subscription_matched( DataReader*, const SubscriptionMatchedStatus& info) { if (info.current_count_change == 1) { - matched_ = info.total_count; + matched_ = info.current_count; std::cout << "Subscriber matched." << std::endl; } else if (info.current_count_change == -1) { - matched_ = info.total_count; + matched_ = info.current_count; std::cout << "Subscriber unmatched." << std::endl; } else @@ -156,13 +140,13 @@ void CustomFilterSubscriber::SubListener::on_subscription_matched( } } -void CustomFilterSubscriber::SubListener::on_data_available( +void ContentFilteredTopicExampleSubscriber::on_data_available( DataReader* reader) { SampleInfo info; - if (reader->take_next_sample(&hello_, &info) == ReturnCode_t::RETCODE_OK) + if (ReturnCode_t::RETCODE_OK == reader->take_next_sample(&hello_, &info)) { - if (info.instance_state == ALIVE_INSTANCE_STATE) + if (ALIVE_INSTANCE_STATE == info.instance_state) { samples_++; // Print your structure data here. @@ -171,18 +155,8 @@ void CustomFilterSubscriber::SubListener::on_data_available( } } -void CustomFilterSubscriber::run() +void ContentFilteredTopicExampleSubscriber::run() { std::cout << "Subscriber running. Please press enter to stop the Subscriber" << std::endl; std::cin.ignore(); } - -void CustomFilterSubscriber::run( - uint32_t number) -{ - std::cout << "Subscriber running until " << number << "samples have been received" << std::endl; - while (number > listener_.samples_) - { - std::this_thread::sleep_for(std::chrono::milliseconds(500)); - } -} diff --git a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.hpp b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.hpp index dbbc8511de8..d4aa9f31838 100644 --- a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.hpp +++ b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.hpp @@ -1,4 +1,4 @@ -// Copyright 2021 Proyectos y Sistemas de Mantenimiento SL (eProsima). +// Copyright 2022 Proyectos y Sistemas de Mantenimiento SL (eProsima). // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -13,28 +13,34 @@ // limitations under the License. /** - * @file CustomFilterSubscriber.hpp + * @file ContentFilteredTopicExampleSubscriber.hpp * */ -#ifndef _DEFAULTSQLFILTERSUBSCRIBER_HPP_ -#define _DEFAULTSQLFILTERSUBSCRIBER_HPP_ +#ifndef _CONTENTFILTEREDTOPICEXAMPLESUBSCRIBER_HPP_ +#define _CONTENTFILTEREDTOPICEXAMPLESUBSCRIBER_HPP_ #include "HelloWorldPubSubTypes.h" -#include "MyCustomFilterFactory.hpp" +#include #include +#include #include -#include -#include +#include +#include +#include +#include +#include -class CustomFilterSubscriber +#include "MyCustomFilterFactory.hpp" + +class ContentFilteredTopicExampleSubscriber : public eprosima::fastdds::dds::DataReaderListener { public: - CustomFilterSubscriber() = default; + ContentFilteredTopicExampleSubscriber() = default; - virtual ~CustomFilterSubscriber(); + virtual ~ContentFilteredTopicExampleSubscriber(); /** * @brief Initialize the subscriber @@ -47,13 +53,9 @@ class CustomFilterSubscriber bool init( bool custom_filter = false); - //!RUN the subscriber + //! Run the subscriber void run(); - //!Run the subscriber until number samples have been received. - void run( - uint32_t number); - private: eprosima::fastdds::dds::DomainParticipant* participant_ = nullptr; @@ -70,28 +72,19 @@ class CustomFilterSubscriber MyCustomFilterFactory filter_factory; - class SubListener : public eprosima::fastdds::dds::DataReaderListener - { - public: - - ~SubListener() override - { - } + HelloWorld hello_; - void on_data_available( - eprosima::fastdds::dds::DataReader* reader) override; + int matched_ = 0; - void on_subscription_matched( - eprosima::fastdds::dds::DataReader* reader, - const eprosima::fastdds::dds::SubscriptionMatchedStatus& info) override; + uint32_t samples_ = 0; - HelloWorld hello_; + void on_data_available( + eprosima::fastdds::dds::DataReader* reader) override; - int matched_ = 0; + void on_subscription_matched( + eprosima::fastdds::dds::DataReader* reader, + const eprosima::fastdds::dds::SubscriptionMatchedStatus& info) override; - uint32_t samples_ = 0; - } - listener_; }; -#endif // _DEFAULTSQLFILTERSUBSCRIBER_HPP_ +#endif // _CONTENTFILTEREDTOPICEXAMPLESUBSCRIBER_HPP_ diff --git a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExample_main.cpp b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExample_main.cpp index c3bc2c863b9..643fb9cb08a 100644 --- a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExample_main.cpp +++ b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExample_main.cpp @@ -70,7 +70,7 @@ int main( { case 1: { - CustomFilterPublisher mypub; + ContentFilteredTopicExamplePublisher mypub; if (mypub.init()) { mypub.run(static_cast(count), static_cast(sleep)); @@ -79,7 +79,7 @@ int main( } case 2: { - CustomFilterSubscriber mysub; + ContentFilteredTopicExampleSubscriber mysub; if (mysub.init(custom_filter)) { mysub.run(); diff --git a/examples/C++/DDS/ContentFilteredTopicExample/MyCustomFilter.hpp b/examples/C++/DDS/ContentFilteredTopicExample/MyCustomFilter.hpp index 979107cbd4d..b57c197a48d 100644 --- a/examples/C++/DDS/ContentFilteredTopicExample/MyCustomFilter.hpp +++ b/examples/C++/DDS/ContentFilteredTopicExample/MyCustomFilter.hpp @@ -1,9 +1,8 @@ -#ifndef _MYCUSTOMFILTER_HPP_ -#define _MYCUSTOMFILTER_HPP_ - -#include +#ifndef _CONTENTFILTEREDTOPICEXAMPLE_MYCUSTOMFILTER_HPP_ +#define _CONTENTFILTEREDTOPICEXAMPLE_MYCUSTOMFILTER_HPP_ #include +#include class MyCustomFilter : public eprosima::fastdds::dds::IContentFilter { @@ -58,4 +57,4 @@ class MyCustomFilter : public eprosima::fastdds::dds::IContentFilter }; -#endif // _MYCUSTOMFILTER_HPP_ +#endif // _CONTENTFILTEREDTOPICEXAMPLE_MYCUSTOMFILTER_HPP_ diff --git a/examples/C++/DDS/ContentFilteredTopicExample/MyCustomFilterFactory.hpp b/examples/C++/DDS/ContentFilteredTopicExample/MyCustomFilterFactory.hpp index fb3451954ce..172c357d843 100644 --- a/examples/C++/DDS/ContentFilteredTopicExample/MyCustomFilterFactory.hpp +++ b/examples/C++/DDS/ContentFilteredTopicExample/MyCustomFilterFactory.hpp @@ -1,9 +1,11 @@ -#ifndef _MYCUSTOMFILTERFACTORY_HPP_ -#define _MYCUSTOMFILTERFACTORY_HPP_ - -#include "MyCustomFilter.hpp" +#ifndef _CONTENTFILTEREDTOPICEXAMPLE_MYCUSTOMFILTERFACTORY_HPP_ +#define _CONTENTFILTEREDTOPICEXAMPLE_MYCUSTOMFILTERFACTORY_HPP_ +#include #include +#include + +#include "MyCustomFilter.hpp" class MyCustomFilterFactory : public eprosima::fastdds::dds::IContentFilterFactory { @@ -64,4 +66,4 @@ class MyCustomFilterFactory : public eprosima::fastdds::dds::IContentFilterFacto } }; -#endif // _MYCUSTOMFILTERFACTORY_HPP_ +#endif // _CONTENTFILTEREDTOPICEXAMPLE_MYCUSTOMFILTERFACTORY_HPP_ diff --git a/examples/C++/DDS/ContentFilteredTopicExample/README.md b/examples/C++/DDS/ContentFilteredTopicExample/README.md index ccc1f5ebc65..191f079dae0 100644 --- a/examples/C++/DDS/ContentFilteredTopicExample/README.md +++ b/examples/C++/DDS/ContentFilteredTopicExample/README.md @@ -18,4 +18,5 @@ Custom Subscriber should received samples which index is lower than 3 and greate ## Arguments First argument is mandatory and it should be one of the following values: `publisher`, `default_subscriber` and `custom_subscriber`. -The `publisher` can be launched specifying the number of samples to be sent (10 by default) and the sleep between samples in [ms] (by default 100 ms) in that order. \ No newline at end of file +The `publisher` can be launched specifying the number of samples to be sent (10 by default) and the sleep between samples in [ms] (by default 100 ms) in that order. +If the number of samples is 0, then the `publisher` is writing samples continously. From 3a9c5a09c8c647ffbc1cf5a208ade9323ccd6091 Mon Sep 17 00:00:00 2001 From: JLBuenoLopez-eProsima Date: Wed, 6 Apr 2022 15:27:23 +0200 Subject: [PATCH 08/17] Refs #14220: linters Signed-off-by: JLBuenoLopez-eProsima --- .../ContentFilteredTopicExampleSubscriber.cpp | 2 +- .../ContentFilteredTopicExampleSubscriber.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.cpp b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.cpp index 3d1f153e6f9..29dc44dcd5a 100644 --- a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.cpp +++ b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.cpp @@ -76,7 +76,7 @@ bool ContentFilteredTopicExampleSubscriber::init( std::vector parameters; if (custom_filter) { - // Custom filter: reject samples where index > parameters[0] and index < parameters[1]. + // Custom filter: reject samples where index > parameters[0] and index < parameters[1]. expression = " "; parameters.push_back("3"); parameters.push_back("5"); diff --git a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.hpp b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.hpp index d4aa9f31838..b944e99eba8 100644 --- a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.hpp +++ b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.hpp @@ -44,7 +44,7 @@ class ContentFilteredTopicExampleSubscriber : public eprosima::fastdds::dds::Dat /** * @brief Initialize the subscriber - * + * * @param custom_filter Whether the default SQL filter or the custom defined filter is used. * By default the SQL filter is used. * @return true if correctly initialized. From bd054f5318bb8668b520260f902c4f8e41250847 Mon Sep 17 00:00:00 2001 From: JLBuenoLopez-eProsima Date: Mon, 11 Apr 2022 11:25:32 +0200 Subject: [PATCH 09/17] Refs #14220: Use argument parser Signed-off-by: JLBuenoLopez-eProsima --- .../CMakeLists.txt | 2 +- .../ContentFilteredTopicExample_main.cpp | 180 +++++++++++++++--- 2 files changed, 158 insertions(+), 24 deletions(-) diff --git a/examples/C++/DDS/ContentFilteredTopicExample/CMakeLists.txt b/examples/C++/DDS/ContentFilteredTopicExample/CMakeLists.txt index d360d423004..1ea5c1f73cb 100644 --- a/examples/C++/DDS/ContentFilteredTopicExample/CMakeLists.txt +++ b/examples/C++/DDS/ContentFilteredTopicExample/CMakeLists.txt @@ -42,6 +42,6 @@ target_compile_definitions(DDSContentFilteredTopicExample PRIVATE $<$:__INTERNALDEBUG> # Internal debug activated. ) target_compile_features(DDSContentFilteredTopicExample PRIVATE cxx_std_11) -target_link_libraries(DDSContentFilteredTopicExample fastrtps fastcdr) +target_link_libraries(DDSContentFilteredTopicExample fastrtps fastcdr fastdds::optionparser) install(TARGETS DDSContentFilteredTopicExample RUNTIME DESTINATION examples/C++/DDS/ContentFilteredTopicExample/${BIN_INSTALL_DIR}) diff --git a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExample_main.cpp b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExample_main.cpp index 643fb9cb08a..2dd2ed16b73 100644 --- a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExample_main.cpp +++ b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExample_main.cpp @@ -17,53 +17,187 @@ * */ +#include + +#include +#include + #include "ContentFilteredTopicExamplePublisher.hpp" #include "ContentFilteredTopicExampleSubscriber.hpp" -#include +using eprosima::fastdds::dds::Log; +namespace option = eprosima::option; -#include +struct Arg : public option::Arg +{ + static void print_error( + const char* msg1, + const option::Option& opt, + const char* msg2) + { + fprintf(stderr, "%s", msg1); + fwrite(opt.name, opt.namelen, 1, stderr); + fprintf(stderr, "%s", msg2); + } -using eprosima::fastdds::dds::Log; + static option::ArgStatus Unknown( + const option::Option& option, + bool msg) + { + if (msg) + { + print_error("Unknown option '", option, "'\n"); + } + return option::ARG_ILLEGAL; + } + + static option::ArgStatus Numeric( + const option::Option& option, + bool msg) + { + char* endptr = 0; + if (nullptr != option.arg) + { + strtol(option.arg, &endptr, 10); + if (endptr != option.arg && *endptr == 0) + { + return option::ARG_OK; + } + } + if (msg) + { + print_error("Option '", option, "' requires a numeric argument\n"); + } + return option::ARG_ILLEGAL; + } + + static option::ArgStatus String( + const option::Option& option, + bool msg) + { + if (nullptr != option.arg) + { + return option::ARG_OK; + } + if (msg) + { + print_error("Option '", option, "' requires a string argument\n"); + } + return option::ARG_ILLEGAL; + } +}; + +enum optionIndex +{ + UNKNOWN_OPTION, + HELP, + PUBLISHER, + SUBSCRIBER, + SAMPLES, + INTERVAL, + FILTER +}; + +const option::Descriptor usage[] = { + { UNKNOWN_OPTION, 0, "", "", Arg::None, + "Usage: ContentFilteredTopicExample [--publisher|--subscriber] [OPTIONS]\n\nGeneral options:" }, + { HELP, 0, "h", "help", Arg::None, " -h\t--help\tProduce help message." }, + { PUBLISHER, 0, "", "publisher", Arg::None, "\t--publisher\tLaunch publisher application." }, + { SUBSCRIBER, 0, "", "subscriber", Arg::None, "\t--subscriber\tLaunch subscriber application." }, + + { UNKNOWN_OPTION, 0, "", "", Arg::None, "\nPublisher options:" }, + { SAMPLES, 0, "s", "samples", Arg::Numeric, + " -s \t--samples=\tNumber of samples (Default: 0 => infinite samples)." }, + { INTERVAL, 0, "i", "interval", Arg::Numeric, + " -i \t--interval=\tTime between samples in milliseconds (Default: 100 ms)." }, + + { UNKNOWN_OPTION, 0, "", "", Arg::None, "\nSubscriber options:" }, + { FILTER, 0, "f", "filter", Arg::String, + " -f \t--filter=\tKind of Content Filter to use (Default: DDS SQL default filter" + }, + + { 0, 0, 0, 0, 0, 0 } +}; int main( int argc, char** argv) { std::cout << "Starting " << std::endl; + + // Parse arguments using optionparser + argc -= (argc > 0); + argv += (argc > 0); // skip program name argv[0] if present + option::Stats stats(usage, argc, argv); + std::vector options(stats.options_max); + std::vector buffer(stats.buffer_max); + option::Parser parse(usage, argc, argv, &options[0], &buffer[0]); + if (parse.error()) + { + return 1; + } + + if (options[HELP]) + { + option::printUsage(fwrite, stdout, usage); + return 0; + } + int type = 1; - int count = 10; + int count = 0; int sleep = 100; bool custom_filter = false; - if (argc > 1) + if (options[PUBLISHER] && options[SUBSCRIBER]) + { + std::cout << "ERROR: select either publisher or subscriber option" << std::endl; + option::printUsage(fwrite, stdout, usage); + return 1; + } + else if (options[PUBLISHER]) { - if (strcmp(argv[1], "publisher") == 0) + if (options[FILTER]) { - type = 1; - if (argc >= 3) - { - count = atoi(argv[2]); - if (argc == 4) - { - sleep = atoi(argv[3]); - } - } + std::cout << "ERROR: option filter is a subscriber option" << std::endl; + option::printUsage(fwrite, stdout, usage); + return 1; + } + if (options[SAMPLES]) + { + count = strtol(options[SAMPLES].arg, nullptr, 10); + } + if (options[INTERVAL]) + { + sleep = strtol(options[INTERVAL].arg, nullptr, 10); } - else if (strcmp(argv[1], "default_subscriber") == 0) + } + else if (options[SUBSCRIBER]) + { + type = 2; + if (options[SAMPLES] || options[INTERVAL]) { - type = 2; + std::cout << "ERROR: options samples and interval are publisher options" << std::endl; + option::printUsage(fwrite, stdout, usage); + return 1; } - else if (strcmp(argv[1], "custom_subscriber") == 0) + if (options[FILTER]) { - type = 2; - custom_filter = true; + if (0 == strcmp(options[FILTER].arg, "custom")) + { + custom_filter = true; + } + else if (0 != strcmp(options[FILTER].arg, "default")) + { + std::cout << "ERROR: filter option should be either custom or default" << std::endl; + option::printUsage(fwrite, stdout, usage); + return 1; + } } } else { - std::cout << "publisher OR subscriber argument needed" << std::endl; - Log::Reset(); - return 0; + std::cout << "ERROR: select either publisher or subscriber option" << std::endl; + option::printUsage(fwrite, stdout, usage); + return 1; } switch (type) From fa76a98b743f1e45d631c95171bc34c3f2f4e78f Mon Sep 17 00:00:00 2001 From: JLBuenoLopez-eProsima Date: Mon, 11 Apr 2022 11:36:09 +0200 Subject: [PATCH 10/17] Refs #14220: apply code review suggestions Signed-off-by: JLBuenoLopez-eProsima --- .../ContentFilteredTopicExamplePublisher.hpp | 8 ++++--- .../MyCustomFilterFactory.hpp | 22 +++++++------------ 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.hpp b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.hpp index 6ae231c03a0..6400b92e710 100644 --- a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.hpp +++ b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.hpp @@ -20,6 +20,8 @@ #ifndef _CONTENTFILTEREDTOPICEXAMPLEPUBLISHER_H_ #define _CONTENTFILTEREDTOPICEXAMPLEPUBLISHER_H_ +#include + #include #include #include @@ -64,11 +66,11 @@ class ContentFilteredTopicExamplePublisher : public eprosima::fastdds::dds::Data eprosima::fastdds::dds::TypeSupport type_ = eprosima::fastdds::dds::TypeSupport(new HelloWorldPubSubType()); - bool stop_; + std::atomic stop_; - int matched_; + std::atomic matched_; - bool firstConnected_; + std::atomic firstConnected_; void on_publication_matched( eprosima::fastdds::dds::DataWriter* writer, diff --git a/examples/C++/DDS/ContentFilteredTopicExample/MyCustomFilterFactory.hpp b/examples/C++/DDS/ContentFilteredTopicExample/MyCustomFilterFactory.hpp index 172c357d843..5b602c2f00d 100644 --- a/examples/C++/DDS/ContentFilteredTopicExample/MyCustomFilterFactory.hpp +++ b/examples/C++/DDS/ContentFilteredTopicExample/MyCustomFilterFactory.hpp @@ -20,19 +20,11 @@ class MyCustomFilterFactory : public eprosima::fastdds::dds::IContentFilterFacto eprosima::fastdds::dds::IContentFilter*& filter_instance) override { // Check the ContentFilteredTopic should be created by my factory. - if (0 != strcmp(filter_class_name, "MY_CUSTOM_FILTER")) - { - return ReturnCode_t::RETCODE_BAD_PARAMETER; - } - - // Check the ContentFilteredTopic is created for the unique type this Custom Filter supports. - if (0 != strcmp(type_name, "HelloWorld")) - { - return ReturnCode_t::RETCODE_BAD_PARAMETER; - } - - // Checks there were set the two mandatory filter parameters. - if (2 != filter_parameters.length()) + if (0 != strcmp(filter_class_name, "MY_CUSTOM_FILTER") || + // Check the ContentFilteredTopic is created for the unique type this Custom Filter supports. + 0 != strcmp(type_name, "HelloWorld") || + // Checks there were set the two mandatory filter parameters. + 2 != filter_parameters.length()) { return ReturnCode_t::RETCODE_BAD_PARAMETER; } @@ -54,7 +46,9 @@ class MyCustomFilterFactory : public eprosima::fastdds::dds::IContentFilterFacto eprosima::fastdds::dds::IContentFilter* filter_instance) override { // Check the ContentFilteredTopic should be created by my factory. - if (0 != strcmp(filter_class_name, "MY_CUSTOM_FILTER")) + if (0 != strcmp(filter_class_name, "MY_CUSTOM_FILTER") || + // Check the filter instance is valid + nullptr != filter_instance) { return ReturnCode_t::RETCODE_BAD_PARAMETER; } From 662745f64fa18dd1e9671508e879cf8b83473474 Mon Sep 17 00:00:00 2001 From: JLBuenoLopez-eProsima Date: Mon, 11 Apr 2022 11:37:46 +0200 Subject: [PATCH 11/17] Refs #14220: linters Signed-off-by: JLBuenoLopez-eProsima --- .../ContentFilteredTopicExample_main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExample_main.cpp b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExample_main.cpp index 2dd2ed16b73..1256872d3a5 100644 --- a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExample_main.cpp +++ b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExample_main.cpp @@ -85,6 +85,7 @@ struct Arg : public option::Arg } return option::ARG_ILLEGAL; } + }; enum optionIndex From 1f8b8692825be2955fbd1f5bbf768daf2c871582 Mon Sep 17 00:00:00 2001 From: JLBuenoLopez-eProsima Date: Mon, 11 Apr 2022 11:49:09 +0200 Subject: [PATCH 12/17] Refs #14220: fix argument parser if option is unknown Signed-off-by: JLBuenoLopez-eProsima --- .../ContentFilteredTopicExample_main.cpp | 27 ++++++++----------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExample_main.cpp b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExample_main.cpp index 1256872d3a5..d00302fa48e 100644 --- a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExample_main.cpp +++ b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExample_main.cpp @@ -40,17 +40,6 @@ struct Arg : public option::Arg fprintf(stderr, "%s", msg2); } - static option::ArgStatus Unknown( - const option::Option& option, - bool msg) - { - if (msg) - { - print_error("Unknown option '", option, "'\n"); - } - return option::ARG_ILLEGAL; - } - static option::ArgStatus Numeric( const option::Option& option, bool msg) @@ -143,6 +132,12 @@ int main( option::printUsage(fwrite, stdout, usage); return 0; } + else if (options[UNKNOWN_OPTION]) + { + std::cerr << "ERROR: " << options[UNKNOWN_OPTION].name << " is not a valid argument." << std::endl; + option::printUsage(fwrite, stdout, usage); + return 1; + } int type = 1; int count = 0; @@ -150,7 +145,7 @@ int main( bool custom_filter = false; if (options[PUBLISHER] && options[SUBSCRIBER]) { - std::cout << "ERROR: select either publisher or subscriber option" << std::endl; + std::cerr << "ERROR: select either publisher or subscriber option" << std::endl; option::printUsage(fwrite, stdout, usage); return 1; } @@ -158,7 +153,7 @@ int main( { if (options[FILTER]) { - std::cout << "ERROR: option filter is a subscriber option" << std::endl; + std::cerr << "ERROR: option filter is a subscriber option" << std::endl; option::printUsage(fwrite, stdout, usage); return 1; } @@ -176,7 +171,7 @@ int main( type = 2; if (options[SAMPLES] || options[INTERVAL]) { - std::cout << "ERROR: options samples and interval are publisher options" << std::endl; + std::cerr << "ERROR: options samples and interval are publisher options" << std::endl; option::printUsage(fwrite, stdout, usage); return 1; } @@ -188,7 +183,7 @@ int main( } else if (0 != strcmp(options[FILTER].arg, "default")) { - std::cout << "ERROR: filter option should be either custom or default" << std::endl; + std::cerr << "ERROR: filter option should be either custom or default" << std::endl; option::printUsage(fwrite, stdout, usage); return 1; } @@ -196,7 +191,7 @@ int main( } else { - std::cout << "ERROR: select either publisher or subscriber option" << std::endl; + std::cerr << "ERROR: select either publisher or subscriber option" << std::endl; option::printUsage(fwrite, stdout, usage); return 1; } From b0113284afda922758e83620fb18071ff7ddc964 Mon Sep 17 00:00:00 2001 From: JLBuenoLopez-eProsima Date: Mon, 11 Apr 2022 13:08:58 +0200 Subject: [PATCH 13/17] Refs #14220: improve documentation Signed-off-by: JLBuenoLopez-eProsima --- .../ContentFilteredTopicExamplePublisher.cpp | 28 +++++++++++---- .../ContentFilteredTopicExamplePublisher.hpp | 16 ++++++++- .../ContentFilteredTopicExampleSubscriber.cpp | 36 +++++++++++-------- .../ContentFilteredTopicExampleSubscriber.hpp | 22 ++++++++++-- .../ContentFilteredTopicExample_main.cpp | 25 ++++++++++++- .../MyCustomFilter.hpp | 16 +++++++++ .../MyCustomFilterFactory.hpp | 17 +++++++-- 7 files changed, 131 insertions(+), 29 deletions(-) diff --git a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.cpp b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.cpp index f9eb6141405..c82eab0dd5f 100644 --- a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.cpp +++ b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.cpp @@ -33,38 +33,39 @@ using namespace eprosima::fastdds::dds; bool ContentFilteredTopicExamplePublisher::init() { + // Initialize data sample hello_.index(0); hello_.message("HelloWorld"); + + // Set DomainParticipant name DomainParticipantQos pqos; pqos.name("Participant_pub"); + // Create DomainParticipant in domain 0 participant_ = DomainParticipantFactory::get_instance()->create_participant(0, pqos); - if (nullptr == participant_) { return false; } - //REGISTER THE TYPE + // Register the type type_.register_type(participant_); - //CREATE THE PUBLISHER + // Create the Publisher publisher_ = participant_->create_publisher(PUBLISHER_QOS_DEFAULT, nullptr); - if (nullptr == publisher_) { return false; } + // Create the Topic topic_ = participant_->create_topic("HelloWorldTopic", type_->getName(), TOPIC_QOS_DEFAULT); - if (nullptr == topic_) { return false; } - // CREATE THE WRITER + // Create the DataWriter writer_ = publisher_->create_datawriter(topic_, DATAWRITER_QOS_DEFAULT, this); - if (nullptr == writer_) { return false; @@ -74,7 +75,9 @@ bool ContentFilteredTopicExamplePublisher::init() ContentFilteredTopicExamplePublisher::~ContentFilteredTopicExamplePublisher() { + // Delete DDS entities contained within the DomainParticipant participant_->delete_contained_entities(); + // Delete DomainParticipant DomainParticipantFactory::get_instance()->delete_participant(participant_); } @@ -82,17 +85,20 @@ void ContentFilteredTopicExamplePublisher::on_publication_matched( DataWriter*, const PublicationMatchedStatus& info) { + // New remote DataReader discovered if (info.current_count_change == 1) { matched_ = info.current_count; firstConnected_ = true; std::cout << "Publisher matched." << std::endl; } + // New remote DataReader undiscovered else if (info.current_count_change == -1) { matched_ = info.current_count; std::cout << "Publisher unmatched." << std::endl; } + // Non-valid option else { std::cout << info.current_count_change @@ -104,6 +110,7 @@ void ContentFilteredTopicExamplePublisher::runThread( uint32_t samples, uint32_t sleep) { + // Publish samples continously until stopped by the user if (samples == 0) { while (!stop_) @@ -116,6 +123,7 @@ void ContentFilteredTopicExamplePublisher::runThread( std::this_thread::sleep_for(std::chrono::milliseconds(sleep)); } } + // Publish given number of samples else { for (uint32_t i = 0; i < samples; ++i) @@ -138,14 +146,17 @@ void ContentFilteredTopicExamplePublisher::run( uint32_t samples, uint32_t sleep) { + // Spawn publisher application thread stop_ = false; std::thread thread(&ContentFilteredTopicExamplePublisher::runThread, this, samples, sleep); + // Thread runs indefinitely until stopped by the user if (samples == 0) { std::cout << "Publisher running. Please press enter to stop the Publisher at any time." << std::endl; std::cin.ignore(); stop_ = true; } + // Thread runs only for the given samples else { std::cout << "Publisher running " << samples << " samples." << std::endl; @@ -156,9 +167,12 @@ void ContentFilteredTopicExamplePublisher::run( bool ContentFilteredTopicExamplePublisher::publish( bool waitForListener) { + // Wait until there is a matched DataReader, unless waitForListener flag is set to false if (firstConnected_ || !waitForListener || matched_ > 0) { + // Update sample hello_.index(hello_.index() + 1); + // Write sample writer_->write(&hello_); return true; } diff --git a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.hpp b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.hpp index 6400b92e710..f5668b66dfd 100644 --- a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.hpp +++ b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.hpp @@ -32,12 +32,15 @@ #include "HelloWorldPubSubTypes.h" +//! Publisher application class class ContentFilteredTopicExamplePublisher : public eprosima::fastdds::dds::DataWriterListener { public: + //! Constructor ContentFilteredTopicExamplePublisher() = default; + //! Destructor virtual ~ContentFilteredTopicExamplePublisher(); //! Initialize @@ -47,35 +50,46 @@ class ContentFilteredTopicExamplePublisher : public eprosima::fastdds::dds::Data bool publish( bool waitForListener = true); - //! Run for number samples + //! Run for the given number of samples (0 => infinite samples) void run( uint32_t number, uint32_t sleep); private: + //! Data type HelloWorld hello_; + //! DDS DomainParticipant pointer eprosima::fastdds::dds::DomainParticipant* participant_ = nullptr; + //! DDS Publisher pointer eprosima::fastdds::dds::Publisher* publisher_ = nullptr; + //! DDS Topic pointer eprosima::fastdds::dds::Topic* topic_ = nullptr; + //! DDS DataWriter pointer eprosima::fastdds::dds::DataWriter* writer_ = nullptr; + //! DDS TypeSupport pointer eprosima::fastdds::dds::TypeSupport type_ = eprosima::fastdds::dds::TypeSupport(new HelloWorldPubSubType()); + //! Flag to terminate application std::atomic stop_; + //! Number of DataReaders matched with the publisher application std::atomic matched_; + //! Flag set once the first subscriber is discovered and matched std::atomic firstConnected_; + //! Discovery callback specialization when the DataWriter received discovery information from a remote DataReader void on_publication_matched( eprosima::fastdds::dds::DataWriter* writer, const eprosima::fastdds::dds::PublicationMatchedStatus& info) override; + //! Publisher application thread void runThread( uint32_t number, uint32_t sleep); diff --git a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.cpp b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.cpp index 29dc44dcd5a..3d5dac42c13 100644 --- a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.cpp +++ b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.cpp @@ -32,51 +32,52 @@ using namespace eprosima::fastdds::dds; bool ContentFilteredTopicExampleSubscriber::init( bool custom_filter) { + // Set DomainParticipant name DomainParticipantQos pqos; pqos.name("Participant_sub"); + // Create DomainParticipant participant_ = DomainParticipantFactory::get_instance()->create_participant(0, pqos); - if (nullptr == participant_) { return false; } + // If using the custom filter if (custom_filter) { // Register the filter factory if (ReturnCode_t::RETCODE_OK != participant_->register_content_filter_factory("MY_CUSTOM_FILTER", &filter_factory)) { - // Error return false; } } - //Register the type + // Register the type type_.register_type(participant_); - //CREATE THE SUBSCRIBER + // Create the Subscriber subscriber_ = participant_->create_subscriber(SUBSCRIBER_QOS_DEFAULT, nullptr); - if (nullptr == subscriber_) { return false; } - //Create the topic + // Create the Topic topic_ = participant_->create_topic("HelloWorldTopic", type_->getName(), TOPIC_QOS_DEFAULT); - if (nullptr == topic_) { return false; } - // Create ContentFilteredTopic + // Create the ContentFilteredTopic std::string expression; std::vector parameters; if (custom_filter) { // Custom filter: reject samples where index > parameters[0] and index < parameters[1]. + // Custom filter does not use expression. However, an empty expression disables filtering, so some expression + // must be set. expression = " "; parameters.push_back("3"); parameters.push_back("5"); @@ -86,36 +87,37 @@ bool ContentFilteredTopicExampleSubscriber::init( } else { + // Default filter: accept samples meeting the given expression: index between the two given parameters expression = "index between %0 and %1"; parameters.push_back("5"); parameters.push_back("9"); filter_topic_ = participant_->create_contentfilteredtopic("HelloWorldFilteredTopic1", topic_, expression, parameters); } - if (nullptr == filter_topic_) { - // Error return false; } - // CREATE THE READER + // Create the DataReader DataReaderQos rqos = DATAREADER_QOS_DEFAULT; + // In order to receive all samples, DataReader is configured as RELIABLE and TRANSIENT_LOCAL (ensure reception even + // if DataReader matching is after DataWriter one) rqos.reliability().kind = RELIABLE_RELIABILITY_QOS; rqos.durability().kind = TRANSIENT_LOCAL_DURABILITY_QOS; reader_ = subscriber_->create_datareader(filter_topic_, rqos, this); - if (nullptr == reader_) { return false; } - return true; } ContentFilteredTopicExampleSubscriber::~ContentFilteredTopicExampleSubscriber() { + // Delete DDS entities contained within the DomainParticipant participant_->delete_contained_entities(); + // Delete DomainParticipant DomainParticipantFactory::get_instance()->delete_participant(participant_); } @@ -123,16 +125,19 @@ void ContentFilteredTopicExampleSubscriber::on_subscription_matched( DataReader*, const SubscriptionMatchedStatus& info) { + // New remote DataWriter discovered if (info.current_count_change == 1) { matched_ = info.current_count; std::cout << "Subscriber matched." << std::endl; } + // New remote DataWriter undiscovered else if (info.current_count_change == -1) { matched_ = info.current_count; std::cout << "Subscriber unmatched." << std::endl; } + // Non-valid option else { std::cout << info.current_count_change @@ -144,12 +149,14 @@ void ContentFilteredTopicExampleSubscriber::on_data_available( DataReader* reader) { SampleInfo info; + // Take next sample from DataReader's history if (ReturnCode_t::RETCODE_OK == reader->take_next_sample(&hello_, &info)) { + // Some samples only update the instance state. Only if it is a valid sample (with data) if (ALIVE_INSTANCE_STATE == info.instance_state) { samples_++; - // Print your structure data here. + // Print structure data std::cout << "Message " << hello_.message() << " " << hello_.index() << " RECEIVED" << std::endl; } } @@ -157,6 +164,7 @@ void ContentFilteredTopicExampleSubscriber::on_data_available( void ContentFilteredTopicExampleSubscriber::run() { + // Subscriber application thread running until stopped by the user std::cout << "Subscriber running. Please press enter to stop the Subscriber" << std::endl; std::cin.ignore(); } diff --git a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.hpp b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.hpp index b944e99eba8..37df35eda78 100644 --- a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.hpp +++ b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.hpp @@ -20,7 +20,7 @@ #ifndef _CONTENTFILTEREDTOPICEXAMPLESUBSCRIBER_HPP_ #define _CONTENTFILTEREDTOPICEXAMPLESUBSCRIBER_HPP_ -#include "HelloWorldPubSubTypes.h" +#include #include #include @@ -32,14 +32,18 @@ #include #include +#include "HelloWorldPubSubTypes.h" #include "MyCustomFilterFactory.hpp" +// Subscriber application class class ContentFilteredTopicExampleSubscriber : public eprosima::fastdds::dds::DataReaderListener { public: + //! Constructor ContentFilteredTopicExampleSubscriber() = default; + //! Destructor virtual ~ContentFilteredTopicExampleSubscriber(); /** @@ -53,34 +57,46 @@ class ContentFilteredTopicExampleSubscriber : public eprosima::fastdds::dds::Dat bool init( bool custom_filter = false); - //! Run the subscriber + //! Run the subscriber application void run(); private: + //! DDS DomainParticipant pointer eprosima::fastdds::dds::DomainParticipant* participant_ = nullptr; + //! DDS Subscriber pointer eprosima::fastdds::dds::Subscriber* subscriber_ = nullptr; + //! DDS Topic pointer eprosima::fastdds::dds::Topic* topic_ = nullptr; + //! DDS ContentFilteredTopic pointer eprosima::fastdds::dds::ContentFilteredTopic* filter_topic_ = nullptr; + //! DDS DataReader pointer eprosima::fastdds::dds::DataReader* reader_ = nullptr; + //! DDS TypeSupport pointer eprosima::fastdds::dds::TypeSupport type_ = eprosima::fastdds::dds::TypeSupport(new HelloWorldPubSubType()); + //! Custom filter factory MyCustomFilterFactory filter_factory; + //! Data type HelloWorld hello_; - int matched_ = 0; + //! Number of DataWriters matched with the subscriber application + std::atomic matched_ = 0; + //! Number of received samples uint32_t samples_ = 0; + //! Callback specialization when data is notified to the DataReader void on_data_available( eprosima::fastdds::dds::DataReader* reader) override; + //! Discovery callback specialization when the DataReader receives discovery information from a remote DataWriter void on_subscription_matched( eprosima::fastdds::dds::DataReader* reader, const eprosima::fastdds::dds::SubscriptionMatchedStatus& info) override; diff --git a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExample_main.cpp b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExample_main.cpp index d00302fa48e..691868927a1 100644 --- a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExample_main.cpp +++ b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExample_main.cpp @@ -28,8 +28,10 @@ using eprosima::fastdds::dds::Log; namespace option = eprosima::option; +// Argument checkers struct Arg : public option::Arg { + // Auxiliary method for printing errors while checking arguments static void print_error( const char* msg1, const option::Option& opt, @@ -40,6 +42,7 @@ struct Arg : public option::Arg fprintf(stderr, "%s", msg2); } + // Argument checker for numeric options static option::ArgStatus Numeric( const option::Option& option, bool msg) @@ -60,6 +63,7 @@ struct Arg : public option::Arg return option::ARG_ILLEGAL; } + // Argument checker for string options static option::ArgStatus String( const option::Option& option, bool msg) @@ -77,6 +81,7 @@ struct Arg : public option::Arg }; +// Possible options enum optionIndex { UNKNOWN_OPTION, @@ -88,6 +93,7 @@ enum optionIndex FILTER }; +// Usage description const option::Descriptor usage[] = { { UNKNOWN_OPTION, 0, "", "", Arg::None, "Usage: ContentFilteredTopicExample [--publisher|--subscriber] [OPTIONS]\n\nGeneral options:" }, @@ -116,8 +122,9 @@ int main( std::cout << "Starting " << std::endl; // Parse arguments using optionparser + // skip program name argv[0] if present (optionparser limitation) argc -= (argc > 0); - argv += (argc > 0); // skip program name argv[0] if present + argv += (argc > 0); option::Stats stats(usage, argc, argv); std::vector options(stats.options_max); std::vector buffer(stats.buffer_max); @@ -127,11 +134,13 @@ int main( return 1; } + // If help option selected, print usage description and exit if (options[HELP]) { option::printUsage(fwrite, stdout, usage); return 0; } + // If option is not recognized, print usage description and exit with error code else if (options[UNKNOWN_OPTION]) { std::cerr << "ERROR: " << options[UNKNOWN_OPTION].name << " is not a valid argument." << std::endl; @@ -139,24 +148,29 @@ int main( return 1; } + // Initialize variables with default values int type = 1; int count = 0; int sleep = 100; bool custom_filter = false; + // If both publisher and subscriber options are selected, print usage description and exit with error code if (options[PUBLISHER] && options[SUBSCRIBER]) { std::cerr << "ERROR: select either publisher or subscriber option" << std::endl; option::printUsage(fwrite, stdout, usage); return 1; } + // Publisher option selected else if (options[PUBLISHER]) { + // If any subscriber option is selected, print usage description and exit with error code if (options[FILTER]) { std::cerr << "ERROR: option filter is a subscriber option" << std::endl; option::printUsage(fwrite, stdout, usage); return 1; } + // If any optional publisher option is selected, set the corresponding value if (options[SAMPLES]) { count = strtol(options[SAMPLES].arg, nullptr, 10); @@ -166,21 +180,26 @@ int main( sleep = strtol(options[INTERVAL].arg, nullptr, 10); } } + // Subscriber option selected else if (options[SUBSCRIBER]) { type = 2; + // If any publisher option is selected, print usage description and exit with error code if (options[SAMPLES] || options[INTERVAL]) { std::cerr << "ERROR: options samples and interval are publisher options" << std::endl; option::printUsage(fwrite, stdout, usage); return 1; } + // If any optional subscriber option is selected, set the corresponding value if (options[FILTER]) { if (0 == strcmp(options[FILTER].arg, "custom")) { custom_filter = true; } + // If filter option does not have one of the expected values, print usage description and exit with error + // code else if (0 != strcmp(options[FILTER].arg, "default")) { std::cerr << "ERROR: filter option should be either custom or default" << std::endl; @@ -189,6 +208,7 @@ int main( } } } + // If no publisher or subscriber option has been selected, print usage description and exit with error code else { std::cerr << "ERROR: select either publisher or subscriber option" << std::endl; @@ -200,6 +220,7 @@ int main( { case 1: { + // Initialize and run publisher application ContentFilteredTopicExamplePublisher mypub; if (mypub.init()) { @@ -209,6 +230,7 @@ int main( } case 2: { + // Initialize and run subscriber application ContentFilteredTopicExampleSubscriber mysub; if (mysub.init(custom_filter)) { @@ -217,6 +239,7 @@ int main( break; } } + // Flush Fast DDS Log before closing application Log::Reset(); return 0; } diff --git a/examples/C++/DDS/ContentFilteredTopicExample/MyCustomFilter.hpp b/examples/C++/DDS/ContentFilteredTopicExample/MyCustomFilter.hpp index b57c197a48d..7622ad9b94a 100644 --- a/examples/C++/DDS/ContentFilteredTopicExample/MyCustomFilter.hpp +++ b/examples/C++/DDS/ContentFilteredTopicExample/MyCustomFilter.hpp @@ -4,10 +4,17 @@ #include #include +//! Custom filter class class MyCustomFilter : public eprosima::fastdds::dds::IContentFilter { public: + /** + * @brief Construct a new My Custom Filter object + * + * @param low_mark + * @param high_mark + */ MyCustomFilter( int low_mark, int high_mark) @@ -16,8 +23,15 @@ class MyCustomFilter : public eprosima::fastdds::dds::IContentFilter { } + //! Destructor virtual ~MyCustomFilter() = default; + /** + * @brief Evaluate filter discriminating if the sample is relevant or not meeting the filter criteria + * + * @param payload Serialized sample + * @return true if sample meets filter requirements. false otherwise. + */ bool evaluate( const SerializedPayload& payload, const FilterSampleInfo& /*sample_info*/, @@ -52,7 +66,9 @@ class MyCustomFilter : public eprosima::fastdds::dds::IContentFilter private: + //! Low mark uint32_t low_mark_ = 0; + //! High mark uint32_t high_mark_ = 0; }; diff --git a/examples/C++/DDS/ContentFilteredTopicExample/MyCustomFilterFactory.hpp b/examples/C++/DDS/ContentFilteredTopicExample/MyCustomFilterFactory.hpp index 5b602c2f00d..68323ad1631 100644 --- a/examples/C++/DDS/ContentFilteredTopicExample/MyCustomFilterFactory.hpp +++ b/examples/C++/DDS/ContentFilteredTopicExample/MyCustomFilterFactory.hpp @@ -7,10 +7,20 @@ #include "MyCustomFilter.hpp" +//! Custom filter factory class MyCustomFilterFactory : public eprosima::fastdds::dds::IContentFilterFactory { public: + /** + * @brief Create a ContentFilteredTopic using this factory. Updating the filter implies deleting the previous one + * and creating a new one using the new given parameters. + * + * @param filter_class_name Custom filter name + * @param type_name Data type name + * @param filter_parameters Parameters required by the filter + * @param filter_instance Instance of the filter to be evaluated + */ eprosima::fastrtps::types::ReturnCode_t create_content_filter( const char* filter_class_name, // My custom filter class name is 'MY_CUSTOM_FILTER'. const char* type_name, // This custom filter only supports one type: 'HelloWorld'. @@ -19,11 +29,11 @@ class MyCustomFilterFactory : public eprosima::fastdds::dds::IContentFilterFacto const ParameterSeq& filter_parameters, // Always need two parameters to be set: low_mark and high_mark. eprosima::fastdds::dds::IContentFilter*& filter_instance) override { - // Check the ContentFilteredTopic should be created by my factory. + // Check the ContentFilteredTopic should be created by this factory. if (0 != strcmp(filter_class_name, "MY_CUSTOM_FILTER") || // Check the ContentFilteredTopic is created for the unique type this Custom Filter supports. 0 != strcmp(type_name, "HelloWorld") || - // Checks there were set the two mandatory filter parameters. + // Check that the two mandatory filter parameters were set. 2 != filter_parameters.length()) { return ReturnCode_t::RETCODE_BAD_PARAMETER; @@ -41,11 +51,12 @@ class MyCustomFilterFactory : public eprosima::fastdds::dds::IContentFilterFacto return ReturnCode_t::RETCODE_OK; } + //! Delete a ContentFilteredTopic created by this factory eprosima::fastrtps::types::ReturnCode_t delete_content_filter( const char* filter_class_name, eprosima::fastdds::dds::IContentFilter* filter_instance) override { - // Check the ContentFilteredTopic should be created by my factory. + // Check the ContentFilteredTopic should be created by this factory. if (0 != strcmp(filter_class_name, "MY_CUSTOM_FILTER") || // Check the filter instance is valid nullptr != filter_instance) From 40b5423db30ec69874354fd8e5d22e7552ab6c5d Mon Sep 17 00:00:00 2001 From: JLBuenoLopez-eProsima Date: Mon, 11 Apr 2022 14:21:26 +0200 Subject: [PATCH 14/17] Refs #14220: apply review suggestions to README Signed-off-by: JLBuenoLopez-eProsima --- .../DDS/ContentFilteredTopicExample/README.md | 38 ++++++++++++------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/examples/C++/DDS/ContentFilteredTopicExample/README.md b/examples/C++/DDS/ContentFilteredTopicExample/README.md index 191f079dae0..f15e1927cf2 100644 --- a/examples/C++/DDS/ContentFilteredTopicExample/README.md +++ b/examples/C++/DDS/ContentFilteredTopicExample/README.md @@ -1,22 +1,34 @@ # Content Filtered Topic Example This example extends the HelloWorld example to show how to use Content Filtered Topics. -The example includes the use of two different Filter Factories. -On the one hand the default SQL filter and on the other hand a custom filter defined in the example. +It does so by including two different Filter Factories: on the one hand, the default SQL filter; on the other hand, a custom filter defined in the example. -## Execution instructions +## Execution instructions (Linux platform) -To launch this example open three different consoles: +To launch this example, open three different terminals: -In the first one launch the Subscriber using the default SQL filter: ./DDSContentFilteredTopicExample default_subscriber -In the second one launch the Subscriber using the custom filter: ./DDSContentFilteredTopicExample custom_subscriber -Finally, in the third terminal launch the Publisher: ./DDSContentFilteredTopicExample publisher +In the first one launch the Subscriber using the default SQL filter: -The default Subscriber should received only the samples between indexes 5 and 9. -Custom Subscriber should received samples which index is lower than 3 and greater than 5. +``` +./DDSContentFilteredTopicExample --subscriber +``` -## Arguments +In the second one launch the Subscriber using the custom filter: -First argument is mandatory and it should be one of the following values: `publisher`, `default_subscriber` and `custom_subscriber`. -The `publisher` can be launched specifying the number of samples to be sent (10 by default) and the sleep between samples in [ms] (by default 100 ms) in that order. -If the number of samples is 0, then the `publisher` is writing samples continously. +``` +./DDSContentFilteredTopicExample --subscriber -f custom +``` + +Finally, in the third terminal launch the Publisher: + +``` +./DDSContentFilteredTopicExample --publisher +``` + +The Subscriber with the default filter should received only the samples between indexes 5 and 9, while the Subscriber with the custom filter should received samples which index is lower than 3 and greater than 5. + +In order to know further possible arguments please run + +``` +./DDSContentFilteredTopicExample --help +``` From 7087a85b66f27667eff952011ac7134fdc91b974 Mon Sep 17 00:00:00 2001 From: JLBuenoLopez-eProsima Date: Mon, 11 Apr 2022 14:35:17 +0200 Subject: [PATCH 15/17] Refs #14220: fix clang error Signed-off-by: JLBuenoLopez-eProsima --- .../ContentFilteredTopicExamplePublisher.cpp | 3 +++ .../ContentFilteredTopicExampleSubscriber.cpp | 3 +++ .../ContentFilteredTopicExampleSubscriber.hpp | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.cpp b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.cpp index c82eab0dd5f..74bfd76b1eb 100644 --- a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.cpp +++ b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.cpp @@ -33,6 +33,9 @@ using namespace eprosima::fastdds::dds; bool ContentFilteredTopicExamplePublisher::init() { + // Initialize internal variables + matched_ = 0; + // Initialize data sample hello_.index(0); hello_.message("HelloWorld"); diff --git a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.cpp b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.cpp index 3d5dac42c13..d94053f5f83 100644 --- a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.cpp +++ b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.cpp @@ -32,6 +32,9 @@ using namespace eprosima::fastdds::dds; bool ContentFilteredTopicExampleSubscriber::init( bool custom_filter) { + // Initialize internal variables + matched_ = 0; + // Set DomainParticipant name DomainParticipantQos pqos; pqos.name("Participant_sub"); diff --git a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.hpp b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.hpp index 37df35eda78..1876fe94296 100644 --- a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.hpp +++ b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExampleSubscriber.hpp @@ -87,7 +87,7 @@ class ContentFilteredTopicExampleSubscriber : public eprosima::fastdds::dds::Dat HelloWorld hello_; //! Number of DataWriters matched with the subscriber application - std::atomic matched_ = 0; + std::atomic matched_; //! Number of received samples uint32_t samples_ = 0; From 61a54b128ce1a7bede3ebb93b0c65a32a9497bbd Mon Sep 17 00:00:00 2001 From: JLBuenoLopez-eProsima Date: Mon, 11 Apr 2022 15:35:34 +0200 Subject: [PATCH 16/17] Refs #14220: apply new review suggestion batch Signed-off-by: JLBuenoLopez-eProsima --- .../ContentFilteredTopicExamplePublisher.cpp | 6 ++--- .../ContentFilteredTopicExamplePublisher.hpp | 2 +- .../ContentFilteredTopicExample_main.cpp | 8 +++--- .../MyCustomFilter.hpp | 11 +++++--- .../MyCustomFilterFactory.hpp | 25 ++++++++++++++++--- .../DDS/ContentFilteredTopicExample/README.md | 8 +++--- 6 files changed, 39 insertions(+), 21 deletions(-) diff --git a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.cpp b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.cpp index 74bfd76b1eb..c29edcb3b9e 100644 --- a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.cpp +++ b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.cpp @@ -168,10 +168,10 @@ void ContentFilteredTopicExamplePublisher::run( } bool ContentFilteredTopicExamplePublisher::publish( - bool waitForListener) + bool wait_for_listener) { - // Wait until there is a matched DataReader, unless waitForListener flag is set to false - if (firstConnected_ || !waitForListener || matched_ > 0) + // Wait until there is a matched DataReader, unless wait_for_listener flag is set to false + if (first_connected_ || !wait_for_listener || matched_ > 0) { // Update sample hello_.index(hello_.index() + 1); diff --git a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.hpp b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.hpp index f5668b66dfd..2e9871a6bfd 100644 --- a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.hpp +++ b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.hpp @@ -82,7 +82,7 @@ class ContentFilteredTopicExamplePublisher : public eprosima::fastdds::dds::Data std::atomic matched_; //! Flag set once the first subscriber is discovered and matched - std::atomic firstConnected_; + std::atomic first_connected_; //! Discovery callback specialization when the DataWriter received discovery information from a remote DataReader void on_publication_matched( diff --git a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExample_main.cpp b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExample_main.cpp index 691868927a1..06881a6775d 100644 --- a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExample_main.cpp +++ b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExample_main.cpp @@ -119,8 +119,6 @@ int main( int argc, char** argv) { - std::cout << "Starting " << std::endl; - // Parse arguments using optionparser // skip program name argv[0] if present (optionparser limitation) argc -= (argc > 0); @@ -156,7 +154,7 @@ int main( // If both publisher and subscriber options are selected, print usage description and exit with error code if (options[PUBLISHER] && options[SUBSCRIBER]) { - std::cerr << "ERROR: select either publisher or subscriber option" << std::endl; + std::cerr << "ERROR: select either '--publisher' or '--subscriber' option" << std::endl; option::printUsage(fwrite, stdout, usage); return 1; } @@ -202,7 +200,7 @@ int main( // code else if (0 != strcmp(options[FILTER].arg, "default")) { - std::cerr << "ERROR: filter option should be either custom or default" << std::endl; + std::cerr << "ERROR: filter option should be either 'custom' or 'default'" << std::endl; option::printUsage(fwrite, stdout, usage); return 1; } @@ -211,7 +209,7 @@ int main( // If no publisher or subscriber option has been selected, print usage description and exit with error code else { - std::cerr << "ERROR: select either publisher or subscriber option" << std::endl; + std::cerr << "ERROR: select either '--publisher' or '--subscriber' option" << std::endl; option::printUsage(fwrite, stdout, usage); return 1; } diff --git a/examples/C++/DDS/ContentFilteredTopicExample/MyCustomFilter.hpp b/examples/C++/DDS/ContentFilteredTopicExample/MyCustomFilter.hpp index 7622ad9b94a..d2fbd366585 100644 --- a/examples/C++/DDS/ContentFilteredTopicExample/MyCustomFilter.hpp +++ b/examples/C++/DDS/ContentFilteredTopicExample/MyCustomFilter.hpp @@ -5,12 +5,14 @@ #include //! Custom filter class +//! It requieres two parameters 'low_mark_' and 'high_mark_'. +//! Filter samples which index is lower than 'low_mark_' and higher than 'high_mark_'. class MyCustomFilter : public eprosima::fastdds::dds::IContentFilter { public: /** - * @brief Construct a new My Custom Filter object + * @brief Construct a new MyCustomFilter object * * @param low_mark * @param high_mark @@ -27,7 +29,8 @@ class MyCustomFilter : public eprosima::fastdds::dds::IContentFilter virtual ~MyCustomFilter() = default; /** - * @brief Evaluate filter discriminating if the sample is relevant or not meeting the filter criteria + * @brief Evaluate filter discriminating whether the sample is relevant or not, i.e. whether it meets the filtering + * criteria * * @param payload Serialized sample * @return true if sample meets filter requirements. false otherwise. @@ -66,9 +69,9 @@ class MyCustomFilter : public eprosima::fastdds::dds::IContentFilter private: - //! Low mark + //! Low mark: lower threshold below which the samples are relevant uint32_t low_mark_ = 0; - //! High mark + //! High mark: upper threshold over which the samples are relevant uint32_t high_mark_ = 0; }; diff --git a/examples/C++/DDS/ContentFilteredTopicExample/MyCustomFilterFactory.hpp b/examples/C++/DDS/ContentFilteredTopicExample/MyCustomFilterFactory.hpp index 68323ad1631..deb86feca93 100644 --- a/examples/C++/DDS/ContentFilteredTopicExample/MyCustomFilterFactory.hpp +++ b/examples/C++/DDS/ContentFilteredTopicExample/MyCustomFilterFactory.hpp @@ -13,13 +13,18 @@ class MyCustomFilterFactory : public eprosima::fastdds::dds::IContentFilterFacto public: /** - * @brief Create a ContentFilteredTopic using this factory. Updating the filter implies deleting the previous one - * and creating a new one using the new given parameters. + * @brief Create a ContentFilteredTopic using this factory. + * Updating the filter implies deleting the previous one and creating a new one using the new given + * parameters. * * @param filter_class_name Custom filter name * @param type_name Data type name * @param filter_parameters Parameters required by the filter * @param filter_instance Instance of the filter to be evaluated + * + * @return eprosima::fastrtps::types::ReturnCode_t::RETCODE_BAD_PARAMETER if the requirements for creating the + * ContentFilteredTopic using this factory are not met + * eprosima::fastrtps::types::ReturnCode_t::RETCODE_OK if the ContentFilteredTopic is correctly created */ eprosima::fastrtps::types::ReturnCode_t create_content_filter( const char* filter_class_name, // My custom filter class name is 'MY_CUSTOM_FILTER'. @@ -51,7 +56,16 @@ class MyCustomFilterFactory : public eprosima::fastdds::dds::IContentFilterFacto return ReturnCode_t::RETCODE_OK; } - //! Delete a ContentFilteredTopic created by this factory + /** + * @brief Delete a ContentFilteredTopic created by this factory + * + * @param filter_class_name Custom filter name + * @param filter_instance Instance of the filter to be deleted. + * After returning, the passed pointer becomes invalid. + * @return eprosima::fastrtps::types::ReturnCode_t::RETCODE_BAD_PARAMETER if the instance was created with another + * factory + * eprosima::fastrtps::types::ReturnCode_t::RETCODE_OK if correctly deleted + */ eprosima::fastrtps::types::ReturnCode_t delete_content_filter( const char* filter_class_name, eprosima::fastdds::dds::IContentFilter* filter_instance) override @@ -65,7 +79,10 @@ class MyCustomFilterFactory : public eprosima::fastdds::dds::IContentFilterFacto } // Deletion of the Custom Filter. - delete(dynamic_cast(filter_instance)); + if (nullptr != filter_instance) + { + delete(dynamic_cast(filter_instance)); + } return ReturnCode_t::RETCODE_OK; } diff --git a/examples/C++/DDS/ContentFilteredTopicExample/README.md b/examples/C++/DDS/ContentFilteredTopicExample/README.md index f15e1927cf2..d60e9ece821 100644 --- a/examples/C++/DDS/ContentFilteredTopicExample/README.md +++ b/examples/C++/DDS/ContentFilteredTopicExample/README.md @@ -7,13 +7,13 @@ It does so by including two different Filter Factories: on the one hand, the def To launch this example, open three different terminals: -In the first one launch the Subscriber using the default SQL filter: +In the first one, launch the Subscriber using the default SQL filter: ``` ./DDSContentFilteredTopicExample --subscriber ``` -In the second one launch the Subscriber using the custom filter: +In the second one, launch the Subscriber using the custom filter: ``` ./DDSContentFilteredTopicExample --subscriber -f custom @@ -25,9 +25,9 @@ Finally, in the third terminal launch the Publisher: ./DDSContentFilteredTopicExample --publisher ``` -The Subscriber with the default filter should received only the samples between indexes 5 and 9, while the Subscriber with the custom filter should received samples which index is lower than 3 and greater than 5. +The Subscriber with the default filter should received only the samples between indexes 5 and 9, while the Subscriber with the custom filter should received samples which index is lower than 3 or greater than 5. -In order to know further possible arguments please run +In order to know further possible arguments please run: ``` ./DDSContentFilteredTopicExample --help From 33813b11b74bf256bce5dc4e89201eb378db7d63 Mon Sep 17 00:00:00 2001 From: JLBuenoLopez-eProsima Date: Mon, 11 Apr 2022 15:52:15 +0200 Subject: [PATCH 17/17] Refs #14220: fix building error Signed-off-by: JLBuenoLopez-eProsima --- .../ContentFilteredTopicExamplePublisher.cpp | 2 +- .../ContentFilteredTopicExamplePublisher.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.cpp b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.cpp index c29edcb3b9e..431d8764161 100644 --- a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.cpp +++ b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.cpp @@ -92,7 +92,7 @@ void ContentFilteredTopicExamplePublisher::on_publication_matched( if (info.current_count_change == 1) { matched_ = info.current_count; - firstConnected_ = true; + first_connected_ = true; std::cout << "Publisher matched." << std::endl; } // New remote DataReader undiscovered diff --git a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.hpp b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.hpp index 2e9871a6bfd..ff076dbb364 100644 --- a/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.hpp +++ b/examples/C++/DDS/ContentFilteredTopicExample/ContentFilteredTopicExamplePublisher.hpp @@ -48,7 +48,7 @@ class ContentFilteredTopicExamplePublisher : public eprosima::fastdds::dds::Data //! Publish a sample bool publish( - bool waitForListener = true); + bool wait_for_listener = true); //! Run for the given number of samples (0 => infinite samples) void run(