31.12 Application Acknowledgment

The 47.21 RELIABILITY QosPolicy determines whether or not data published by a DataWriter will be reliably delivered by Connext to matching DataReaders. The reliability protocol used by Connext is discussed in Chapter 32 Reliability Models for Sending Data.

With protocol-level reliability alone, the producing application knows that the information is received by the protocol layer on the consuming side. However, the producing application cannot be certain that the consuming application read that information or was able to successfully understand and process it. The information could arrive in the consumer’s protocol stack and be placed in the DataReader cache but the consuming application could either crash before it reads it from the cache, not read its cache, or read the cache using queries or conditions that prevent that particular DDS data sample from being accessed. Furthermore, the consuming application could access the DDS sample, but not be able to interpret its meaning or process it in the intended way.

The mechanism to let a DataWriter know to keep the DDS sample around, not just until it has been acknowledged by the reliability protocol, but until the application has been able to process the DDS sample is aptly called Application Acknowledgment. A reliable DataWriter will keep the DDS samples until the application acknowledges the DDS samples. When the subscriber application is restarted, the middleware will know that the application did not acknowledge successfully processing the DDS samples and will resend them.

31.12.1 Application Acknowledgment Kinds

Connext supports three kinds of application acknowledgment, which is configured in the 47.21 RELIABILITY QosPolicy):

  1. DDS_PROTOCOL_ACKNOWLEDGMENT_MODE (Default): In essence, this mode is identical to using no application-level acknowledgment. DDS samples are acknowledged according to the Real-Time Publish-Subscribe (RTPS) reliability protocol. RTPS AckNack messages will acknowledge that the middleware received the DDS sample.
  2. DDS_APPLICATION_AUTO_ACKNOWLEDGMENT_MODE: DDS samples are automatically acknowledged by the middleware after the subscribing application accesses them, either through calling take() or read() on the DDS sample. If the read() or take() operation loans the samples, the acknowledgment is done after the return_loan() operation is called. Otherwise, for read() or take() operations that make a copy, acknowledgment is done after the read() or take() operations are executed.
  3. DDS_APPLICATION_EXPLICIT_ACKNOWLEDGMENT_MODE: DDS samples are acknowledged after the subscribing application explicitly calls acknowledge on the DDS sample. This can be done by either calling the DataReader’s acknowledge_sample() or acknowledge_all() operations. When using acknowledge_sample(), the application will provide the DDS_SampleInfo to identify the DDS sample being acknowledge. When using acknowledge_all, all the DDS samples that have been read or taken by the reader will be acknowledged.
  4. Note: Even in DDS_APPLICATION_EXPLICIT_ACKNOWLEDGMENT_MODE, some DDS samples may be automatically acknowledged. This is the case when DDS samples are filtered out by the reader using time-based filter, or using content filters. Additionally, when the reader is explicitly configured to use KEEP_LAST history kind, DDS samples may be replaced in the reader queue due to resource constraints. In that case, the DDS sample will be automatically acknowledged by the middleware if it has not been read by the application before it was replaced. To truly guarantee successful processing of DDS samples, it is recommended to use KEEP_ALL history kind.

31.12.2 Explicitly Acknowledging a Single DDS Sample (C++)

void MyReaderListener::on_data_available(DDSDataReader *reader)
{
	Foo sample;
	DDS_SampleInfo info;
	FooDataReader* fooReader = FooDataReader::narrow(reader);
	DDS_ReturnCode_t retcode = fooReader->take_next_sample(
					sample, info);
	if (retcode == DDS_RETCODE_OK) {
		if (info.valid_data) {
			// Process sample
			...
			retcode = reader->acknowledge_sample(info);
			if (retcode != DDS_RETCODE_OK) {
				// Error
			}
		}
	} else {
		// Not OK or NO DATA
	}
}

31.12.3 Explicitly Acknowledging All DDS samples (C++)

void MyReaderListener::on_data_available(DDSDataReader *reader)
{
	...
	// Loop while samples available
	for(;;) {
		retcode = string_reader->take_next_sample(
				sample, info);
		if (retcode == DDS_RETCODE_NO_DATA) {
			// No more samples
			break;
		}
		// Process sample
		...
	}
	retcode = reader->acknowledge_all();
	if (retcode != DDS_RETCODE_OK) {
		// Error
	}
}

31.12.4 Notification of Delivery with Application Acknowledgment

A DataWriter can get notification of delivery with Application Acknowledgment using two different mechanisms:

  • DataWriter's wait_for_acknowledgments() operation
  • A DataWriter can use the wait_for_acknowledgments() operation to be notified when all the DDS samples in the DataWriter’s queue have been acknowledged. See 31.11 Waiting for Acknowledgments in a DataWriter.

    retCode = fooWriter->write(sample, DDS_HANDLE_NIL);
    if (retCode != DDS_RETCODE_OK) {
       // Error
    }
    retcode = writer->wait_for_acknowledgments(timeout);
    if (retCode != DDS_RETCODE_OK) {
       if (retCode == DDS_RETCODE_TIMEOUT) {
           // Timeout: Sample not acknowledged yet
       } else {
           // Error
       }
    }

    Using wait_for_acknowledgments() does not provide a way to get delivery notifications on a per DataReader and DDS sample basis. If your application requires acknowledgment of message receipt, use the second mechanism described below.

  • DataWriter's listener callback on_application_acknowledgment()
  • An application can install a DataWriter listener callback on_application_acknowledgment() to receive a notification when a DDS sample is acknowledged by a DataReader. As part of this notification, you can access:

    • The subscription handle of the acknowledging DataReader.
    • The Identity of the DDS sample being acknowledged.
    • The response data associated with the DDS sample being acknowledged.

    For more information, see 31.6.1 APPLICATION_ACKNOWLEDGMENT_STATUS.

31.12.5 Application-Level Acknowledgment Protocol

When the subscribing application confirms it has successfully processed a DDS sample, an AppAck RTPS message is sent to the publishing application. This message will be resent until the publishing application confirms receipt of the AppAck message by sending an AppAckConf RTPS message. See Figure 31.2: AppAck RTPS Messages Sent when Application Acknowledges a DDS Sample  through Figure 31.4: AppAck RTPS Messages Sent as a Sequence of Intervals, Combined to Optimize for Bandwidth.

Figure 31.2: AppAck RTPS Messages Sent when Application Acknowledges a DDS Sample 

Figure 31.3: AppAck RTPS Messages Resent Until Acknowledged Through AppAckConf RTPS Message

Figure 31.4: AppAck RTPS Messages Sent as a Sequence of Intervals, Combined to Optimize for Bandwidth

31.12.6 Periodic and Non-Periodic AppAck Messages

You can configure whether AppAck RTPS messages are sent immediately or periodically through the 48.1 DATA_READER_PROTOCOL QosPolicy (DDS Extension). The samples_per_app_ack (in Table 48.2 DDS_RtpsReliableReaderProtocol_t) determines the minimum number of DDS samples acknowledged by one application-level Acknowledgment message. The middleware will not send an AppAck message until it has at least this many DDS samples pending acknowledgment. By default, samples_per_app_ack is 1 and the AppAck RTPS message is sent immediately. Independently, the app_ack_period (in Table 48.2 DDS_RtpsReliableReaderProtocol_t) determines the rate at which a DataReader will send AppAck messages.

31.12.7 Application Acknowledgment and Persistence Service

Application Acknowledgment is fully supported by RTI Persistence Service. The combination of Application Acknowledgment and Persistence Service is actually a common configuration. In addition to keeping DDS samples available until fully acknowledged, Persistence Service, when used in peer-to-peer mode, can take advantage of AppAck messages to avoid sending duplicate messages to the subscribing application. Because AppAck messages are sent to all matching writers, when the subscriber acknowledges the original publisher, Persistence Service will also be notified of this event and will not send out duplicate messages. This is illustrated in Figure 31.5: Application Acknowledgment and Persistence Service .

Figure 31.5: Application Acknowledgment and Persistence Service

31.12.8 Application Acknowledgment and Routing Service

Application Acknowledgment is supported by RTI Routing Service: That is, Routing Service will acknowledge the DDS sample it has processed. Routing Service is an active participant in the Connext system and not transparent to the publisher or subscriber. As such, Routing Service will acknowledge to the publisher, and the subscriber will acknowledge to Routing Service. However, the publisher will not get a notification from the subscriber directly.