Subscriber does not receive first sample

4 posts / 0 new
Last post
asanchez's picture
Offline
Last seen: 6 months 5 days ago
Joined: 11/16/2011
Posts: 50
Subscriber does not receive first sample

Hi all,

I'm running a simple DDS HelloWorld system in my local machine and I'm noticing that I never receive the first sample. The IDl that I'm using is the following:

struct HelloWorld {

     string message;

     long count;

}

On the publisher side the 'count' field is incremented for each sample sent, starting by one. On subscriber side I just print the content of the sample, and I never see the sample whose 'count' field is zero. I don't change any QoS policies, that is, I use the default ones. Also, I first run the subscriber application and the publisher afterwards.

why is this happening?

Antonio

asanchez's picture
Offline
Last seen: 6 months 5 days ago
Joined: 11/16/2011
Posts: 50

After testing for a while I've realized that the problem may be due to the QoS configuration. As I mentioned, I'm using the default profile which turns out to have BEST EFFORT reliability. Hence, there is no guarantee that samples will be delivered.

But then, why did I miss the first sample even if the subscriber application was running before the publisher? If we'd take a look to the code we'd see that inmediately the DataWriter is created, it starts writing data. However, since the discovery runs in a different thread, there is a chance that application has not yet discovered the DataReader from the Subscription side hence not establishing any communication. So if samples were written before discovery, they will not be delivered to the DataReader.

To solve this I modified the profiles to have RELIABLE reliablity with TRANSIENT LOCAL durability and adding KEEP ALL history, for both DataWriter and DataReader:

            <reliability>
                    <kind>RELIABLE_RELIABILITY_QOS</kind>
            </reliability>
            <history>
                    <kind>KEEP_ALL_HISTORY_QOS</kind>
            </history>
            <durability>
                    <kind>TRANSIENT_LOCAL_DURABILITY_QOS</kind>
            </durability>

This way I can receive ALL the samples sent by the DataWriter since the beginning, even though the DataReader joined later.

Antonio

Gerardo Pardo's picture
Offline
Last seen: 1 month 5 days ago
Joined: 06/02/2010
Posts: 594

 

Yes, the RELIABLE QoS by itself only guarantees that a writer will deliver the samples that it has in its DataWriter cache provided that they were written after the Reliable DataReader was discovered. Samples written by a DataWriter prior to discovering the DataReader are only sent to a DataReader if the  DURABILITY QoS Policy kind is set to TRANSIENT_LOCAL, TRANSIENT, or PERSISTENT.  As the default setting of the DURABILITY Qos policy kind is VOLATILE the DataWriter will not send samples that it wrote previous to discovering the DataReader.

As you mentioned discovery is not instantaneus. Assume the subscribing application is already running, has created a DomainParticipant and a DataReader. Then you start the publishing application. Discovery will not commence until you create the DomainParticipant on the publishing side.  If you create the publishing application DomainParticipant, the DataWriter, and immdediately write a sample it is quite likely that these first samples are written befor eteh DomainParticipant has had a chance to discover the DataReader. This is because the creation of the DomainParticipant and DataWriter is very fast, typically faster that whet it takes for the discovery protocol which has to send and receive messages on the network.   As you described discovery uses its own threads (so as to not disrupt the critical operation of applicaton threads), so you will end up writing same samples before the DataReader is created.

If you indeed want to get this "historical" samples, then the best solution is to set the DURABILITY Qos policy to at least TRANSIENT_LOCAL. Note that this policy is request-offered so it needs to be done both on the DataWriter and DataReader in a compatible manner, otherwise you will get an "inconsistent QoS" notification and the DataWriter and DataReader will not communicate at all.

Another option could be to have the DataWriter "wait" for the DataReader to be disovered. THis can be done by observing the PublicationMatchedSatatus which can be read calling the operation get_publication_matched_status on the DataWriter. Or by installing a DataWriterListener and reacting to the on_publication_matched operation. However, other than in special situations this "waiting" approach is not advisable because it couples the publishing application to specific deployent scenarions.  

Note, however, that if the correct execution of the system requires the that certain DataReaders are present and receive the data, as would be the case for certain services that inplement Logging or Data durability, then RTI provides a feature called "durable subscriptions" that directly support this scenarios. This feature is enabled using the AVAILABLITY Qos Policy, which is described in chapters 12 and 13 of the RTI DDS User's Manual.

As a final comment, note also that all these mechanisms only guarantee delivery of data that is present on teh DataWriter cache. If the data is removed due to some policy, like LIFESPAN, or the use of HISTORY with kind KEEP_LAST, or the use of a time or content-based filter, then it fill not be sent to the DataReader.  So if you had a situation where every sample writen by a DataWriter must be delivered to a DataReader, then you should minimally also configure the HISTORY Qos Policy  to KEEP_ALL.

Gerardo

 

Offline
Last seen: 5 years 1 month ago
Joined: 10/11/2015
Posts: 1

I am trying to run the publisher and the subscriber code in the command prompt in Windows . Publisher is Publishing the data , but subscriber is not receiving the messages in its command prompt window.

Why is it not receiving messages ?