Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A subscriber receives RETCODE_NO_DATA with dynamic topic type with @key or @Key [13696] #2215

Closed
davidhjp01 opened this issue Sep 21, 2021 · 7 comments

Comments

@davidhjp01
Copy link

davidhjp01 commented Sep 21, 2021

A subscriber receives return code RETCODE_NO_DATA when a publisher sends a data created using DynamicTypeBuilderFactory with @Key or @key annotation.

Expected Behavior

A subscriber receives a data sent by a publisher

Current Behavior

A subscriber's listener function on_data_available is invoked for each data sent by publisher but read_next_sample returns RETCODE_NO_DATA

Steps to Reproduce

  1. Create .cxx and .h files from .idl (contains a struct with@key annotation for one or more of its members) using fastddsgen with -typeobject argument
  2. Initialise type object/identifier using GetXXXItentifier(true) and GetXXXObject(true).
  3. Register the dynamictype object created by TypeObjectFactory::get_instance()->build_dynamic_type().
  4. Create a topic that uses the registered dynamic type object.
  5. Create publishers and subscribers with listeners
  6. Create dynamic data using DynamicTypeBuilderFactory
  7. Publish data and observe the return code in the subscriber's listener

System information

Intel i9-10885H 32GB RAM

  • Fast-RTPS version: 2.3.3
  • OS: Windows 10
  • Network interfaces:

    Not specified, uses simple discovery mechanism
  • ROS2:

Additional context

Additional resources

  • Wireshark capture
  • XML profiles file
@torbre
Copy link

torbre commented Sep 30, 2021

It would be great if someone in the fast-dds team could look into this issue.

@davidhjp01
Copy link
Author

davidhjp01 commented Oct 20, 2021

Related to #2064

@MiguelCompany After spending some time, I found out that when I create DataType instance via TypeObjectFactory::get_instance()::build_dynamic_Type(), is_key_defined_ in DynamicType (one of the MemberDescriptor's field) is not set to true, which causes a problem in DynamicData::getKeyMaxCdrSerializedSize (line 132 in DynamicPubSubType.cpp) during the creation of TypeSupport (passed as an argument). Basically, the returned keyBufferSize is 0 because the function did not find any key members. DynamicType::is_key_defined_ is checked at line 6087 of DynamicData.cpp.

Also I found that currently FastDDSGen generates the @Key as a custom annotation. Should this be a built-in annotation? Anyways I am attaching a patch that is a quick workaround (neither a best (nor complete) solution) for our use-case, but I believe the FastDDS developers can fix in more proper method:

diff --git a/include/fastrtps/types/AnnotationDescriptor.h b/include/fastrtps/types/AnnotationDescriptor.h
index 2e6762277..365353dae 100644
--- a/include/fastrtps/types/AnnotationDescriptor.h
+++ b/include/fastrtps/types/AnnotationDescriptor.h
@@ -30,10 +30,10 @@ class AnnotationDescriptor
 protected:
     friend class DynamicTypeBuilderFactory;
 
-    DynamicType_ptr type_;
 	std::map<std::string, std::string> value_;
 
 public:
+    DynamicType_ptr type_;
     AnnotationDescriptor();
     ~AnnotationDescriptor();
     AnnotationDescriptor(const AnnotationDescriptor* descriptor);
diff --git a/src/cpp/dynamic-types/MemberDescriptor.cpp b/src/cpp/dynamic-types/MemberDescriptor.cpp
index 755724b9c..5f78048c8 100644
--- a/src/cpp/dynamic-types/MemberDescriptor.cpp
+++ b/src/cpp/dynamic-types/MemberDescriptor.cpp
@@ -702,6 +702,10 @@ ReturnCode_t MemberDescriptor::apply_annotation(AnnotationDescriptor& descriptor
     {
         AnnotationDescriptor* pNewDescriptor = new AnnotationDescriptor();
         pNewDescriptor->copy_from(&descriptor);
+        if (pNewDescriptor->type_->get_name() == "Key" || pNewDescriptor->type_->get_name() == "key") {
+            pNewDescriptor->type_->is_key_defined_ = true;
+            this->type_->is_key_defined_ = true;
+        }
         annotation_.push_back(pNewDescriptor);
         return ReturnCode_t::RETCODE_OK;
     }

@MiguelCompany
Copy link
Member

@davidhjp01 Thank you very much for taking the time to analyze this.

My colleague @richiware has recently created PR #2262, which may be a solution for your issue. I would like his input on your workaround.

It seems to me that the key annotations should be applied both to the members and the DynamicType they belong to.

@richiware
Copy link
Member

Sorry for the inconveniences @davidhjp01 .

If you are using DynamicTypeBuilderFactory to requesting a new DynamicType from a registered TypeObject, as @MiguelCompany suggested, PR #2262 should fix your problem. Would you mind to test your source code against that branch?

Thanks

@davidhjp01
Copy link
Author

Thanks for the follow ups. I tried bugfix/support-Key-annotation but unfortunately I am still getting return code 11. I didn't look carefully into the changes but just tried rebuilt/run tests with the branch.

@davidhjp01
Copy link
Author

davidhjp01 commented Oct 26, 2021

@MiguelCompany, @richiware One question regarding @Key, the following code in SubscriberHistory::lookup_instance at line 672

        auto comp = [](const InstanceHandle_t& h, const std::pair<InstanceHandle_t, KeyedChanges>& it)
                {
                    return h < it.first;
                };
        it = std::upper_bound(keyed_changes_.begin(), keyed_changes_.end(), handle, comp);

only returns the element in keyed_changes_ when the function argument handle is less than the keyed instance handle h < it.first (where the keyed instance handle is initialised in other function with the value of the keyed data received from the publisher). But in DataReaderImpl.cpp line 637, the function argument handle is always HANDLE_NIL (initialized with zero), which means SubscriberHistory::lookup_instance only returns the keyed data if the value of the key is greater than zero.

As a result, FastDDS always returns keyed data when the keyed value is greater than 0. And I am getting RETCODE_NO_DATA (error code 11) whenever the key value is 0. Is this an expected behaviour? I am using DataReader::read_next_sample for reading the received data.

@JLBuenoLopez JLBuenoLopez changed the title A subscriber receives RETCODE_NO_DATA with dynamic topic type with @key or @Key A subscriber receives RETCODE_NO_DATA with dynamic topic type with @key or @Key [13696] Feb 1, 2022
@JesusPoderoso
Copy link
Contributor

I am closing this issue, as it seems that #2316 fixed it, as @davidhjp01 said in this comment in #2306.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants