Dynamic Data Writing Seems to Need a Setup Time

4 posts / 0 new
Last post
Offline
Last seen: 5 years 7 months ago
Joined: 11/07/2014
Posts: 13
Dynamic Data Writing Seems to Need a Setup Time

I've got an application where it monitors for a particular type name. When this type name is found it extracts the type code that corresponds to it, creates dynamic data from the type code, populates the dynamic data, and then publishes (writes) the dynamic data. What I've noticed is that I need to put a "NDDSUtility::sleep" of about 10ms for set up between (create publisher/type registration/create topic/create writer) and the actual writing of the data. If I don't put this delay the write status will report OK, but subscriber's won't see it sometimes. Is a setup time necessary of is there something I'm missing here? This applies to Linux and Windows (but more pronounced).

Thanks for the help.

The below snippet is taken from the "ShapeType using DynamicData" example, but adapted to show what the application does:

....................

publisher = participant->create_publisher(DDS_PUBLISHER_QOS_DEFAULT,
NULL /* listener */, DDS_STATUS_MASK_NONE);
if (publisher == NULL) {
printf("create_publisher error\n");
publisher_shutdown(participant, type_support);
return -1;
}

/* Create DynamicData using TypeCode from Shapes.cxx
* If you are NOT using a type generated with rtiddsgen, you
* need to create this TypeCode from scratch.
*/
type_code = ShapeType_get_typecode();
if (type_code == NULL) {
printf("get_typecode error\n");
publisher_shutdown(participant, type_support);
return -1;
}

/* Create the Dynamic data type support object */
type_support = new DDSDynamicDataTypeSupport(type_code, props);
if (type_support == NULL) {
printf("constructor DynamicDataTypeSupport error\n");
publisher_shutdown(participant, type_support);
return -1;
}

/* Register type before creating topic */
type_name = EXAMPLE_TYPE_NAME;
retcode = type_support->register_type(participant, EXAMPLE_TYPE_NAME);
if (retcode != DDS_RETCODE_OK) {
printf("register_type error\n");
publisher_shutdown(participant, type_support);
return -1;
}

/* Make sure both publisher and subscriber share the same topic
* name.
* In the Shapes example: we are publishing a Square, which is the
* topic name. If you want to publish other shapes (Triangle or
* Circle), you just need to update the topic name. */
topic = participant->create_topic("Square", type_name,
DDS_TOPIC_QOS_DEFAULT, NULL /* listener */, DDS_STATUS_MASK_NONE);
if (topic == NULL) {
printf("create_topic error\n");
publisher_shutdown(participant, type_support);
return -1;
}

/* First, we create a generic DataWriter for our topic */
writer = publisher->create_datawriter(topic, DDS_DATAWRITER_QOS_DEFAULT,
NULL /* listener */, DDS_STATUS_MASK_NONE);
if (writer == NULL) {
printf("create_datawriter error\n");
publisher_shutdown(participant, type_support);
return -1;
}

/* Then, to use DynamicData, we need to assign the generic
* DataWriter to a DynamicDataWriter, using
* DDS_DynamicDataWriter_narrow.
* The following narrow function should never fail, as it performs
* only a safe cast.
*/
DynamicData_writer = DDSDynamicDataWriter::narrow(writer);
if (DynamicData_writer == NULL) {
printf("DynamicData_writer narrow error\n");
publisher_shutdown(participant, type_support);
return -1;
}

-------------------------NDDSUtility::sleep delay goes here----------------------------------------------

/* Create an instance of the sparse data we are about to send */
data = type_support->create_data();

if (data == NULL) {
printf("create_data error\n");
publisher_shutdown(participant, type_support);
return -1;
}

/* Initialize the DynamicData object */
data->set_string("color", DDS_DYNAMIC_DATA_MEMBER_ID_UNSPECIFIED, "BLUE");
data->set_long("x", DDS_DYNAMIC_DATA_MEMBER_ID_UNSPECIFIED, 100);
data->set_long("y", DDS_DYNAMIC_DATA_MEMBER_ID_UNSPECIFIED, 100);
data->set_long("shapesize", DDS_DYNAMIC_DATA_MEMBER_ID_UNSPECIFIED, 30);

/* Write data */
retcode = DynamicData_writer->write(*data, instance_handle);
if (retcode != DDS_RETCODE_OK) {
printf("write error %d\n", retcode);
publisher_shutdown(participant, type_support);
}

/* Delete data sample */
retcode = type_support->delete_data(data);
if (retcode != DDS_RETCODE_OK) {
printf("ShapeTypeTypeSupport::delete_data error %d\n", retcode);
}

rip
rip's picture
Offline
Last seen: 4 days 8 hours ago
Joined: 04/06/2012
Posts: 322

Keep in mind that the creation of an entity is not instantaneous.  There has to be some memory allocation, and then Discovery has to happen, etc, and all that happens (mostly) on a middleware thread and not an application thread.

Due to this threading, it is not entirely without reason that if you create an entity and then immediately "action" it (writer.write() or reader.take() or reader.read()) it may very well be that the "plumbing" hasn't been hooked up yet, that the remote entity hasn't been discovered, etc.

We see this a lot (A LOT) when test and QA engineers write test applications, because they create the writer and immediately write, without even giving Discovery a chance to complete.  Nothing is seen by remote subscribers because the writer doesn't know about them yet.

So a 10mSec "settle" mayn't be unexpected. 

Now, you can tune a really wikidly aggressive Discovery (there is a Gerardo post somewhere here that describes one way to do it).  That is at the cost of really heavy bandwidth and cpu cycle issues, because the middleware spends a lot of time looking for others (stealing that CPU from your application).

But yeah, stick a pause in there in your test applications.  Live applications tend to have a lot more configuration at startup, during which time the Discovery algorithms have a chance to complete, which is why this "problem" is often found by QA, Test and people new to DDS.

"Problem" in quotes, because this is (from the algorithm and protocol standpoint) reasaonbly expected results of the coded behavior.


irp

Offline
Last seen: 5 years 7 months ago
Joined: 11/07/2014
Posts: 13

RIP,

Looks like I did not give proper thought to what I was doing and I guess being new to DDS did not help either.  So it looks like a better approach for Dyanmic Data would be to try do that setup in an earlier stage so data burst could happen later w/o using guess work delays.

I had already given this idea some thought and now with your input I will definetly seek to implement it.

Thanks RIP and RTI for being so helpful,

Doug

rip
rip's picture
Offline
Last seen: 4 days 8 hours ago
Joined: 04/06/2012
Posts: 322

You're welcome!

And it's rip.  RIP is an acronym for "Return Instruction Pointer", an i960 assembler mnemonic.

:)