35.2 Reliable Delivery Model

Reliable delivery means the DDS samples are guaranteed to arrive, in the order published.

The DataWriter maintains a send queue with space to hold the last X number of DDS samples sent. Similarly, a DataReader maintains a receive queue with space for consecutive X expected DDS samples.

The send and receive queues are used to temporarily cache DDS samples until Connext is sure the DDS samples have been delivered and are not needed anymore. Connext removes DDS samples from a publication’s send queue after the DDS sample has been acknowledged by all reliable subscriptions. When positive acknowledgements are disabled (see 59.5 DATA_WRITER_PROTOCOL QosPolicy (DDS Extension) and 60.1 DATA_READER_PROTOCOL QosPolicy (DDS Extension)), DDS samples are removed from the send queue after the corresponding keep-duration has elapsed (see Table 59.14 DDS_RtpsReliableWriterProtocol_t).

If an out-of-order DDS sample arrives, Connext speculatively caches it in the DataReader’s receive queue (provided there is space in the queue). Only consecutive DDS samples are passed on to the DataReader.

DataWriters can be set up to wait for available queue space when sending DDS samples. This will cause the sending thread to block until there is space in the send queue. (Or, you can decide to sacrifice sending DDS samples reliably so that the sending rate is not compromised.) If the DataWriter is set up to ignore the full queue and sends anyway, then older cached DDS samples will be pushed out of the queue before all DataReaders have received them. In this case, the DataReader (or its Subscriber) is notified of the missing DDS samples through its Listener and/or Conditions.

Connext automatically sends acknowledgments (ACKNACKs) as necessary to maintain reliable communications. The DataWriter may choose to block for a specified duration to wait for these acknowledgments (see 34.11 Waiting for Acknowledgments in a DataWriter).

Connext establishes a virtual reliable channel between the matching DataWriter and all DataReaders. This mechanism isolates DataReaders from each other, allows the application to control memory usage, and provides mechanisms for the DataWriter to balance reliability and determinism. Moreover, the use of send and receive queues allows Connext to be implemented efficiently without introducing unnecessary delays in the stream.

Note that a successful return code (DDS_RETCODE_OK) from write() does not necessarily mean that all DataReaders have received the data. It only means that the DDS sample has been added to the DataWriter’s queue. To see if all DataReaders have received the data, look at the 34.6.8 RELIABLE_WRITER_CACHE_CHANGED Status (DDS Extension) to see if any DDS samples are unacknowledged.

Suppose DataWriter A reliably publishes a Topic to which DataReaders B and C reliably subscribe. B has space in its queue, but C does not. Will DataWriter A be notified? Will DataReader C receive any error messages or callbacks? The exact behavior depends on the QoS settings:

  • If HISTORY_KEEP_ALL is specified for C, C will reject DDS samples that cannot be put into the queue and request A to resend missing DDS samples. The Listener is notified with the on_sample_rejected() callback (see 43.7.8 SAMPLE_REJECTED Status). If A has a queue large enough, or A is no longer writing new DDS samples, A won’t notice unless it checks the 34.6.8 RELIABLE_WRITER_CACHE_CHANGED Status (DDS Extension).
  • If HISTORY_KEEP_LAST is specified for C, C will drop old DDS samples and accept new ones. To A, it is as if all DDS samples have been received by C (that is, they have all been acknowledged).