We have what for our DDS4CCM applications is a common use case that is not currently covered by the DDS4CCM v1.1 spec, and the CIAO implementation of it that we use. We would like to propose a minor extension to the DDS4CCM specification to support this use case in accordance with spec paragraph 7.1.1, where it says “the most common DDS use patterns have been then identified as connectors
Specifically, I’m speaking of being able to define a distributed state table via a keyed DDS topic with 1) the ability for a subscriber to receive an event notification/callback for published sample updates to the topic in a DRTE event-driven component framework, combined with 2) a subscriber ability to read the state table information for the topic non-destructively from the reader cache during post-initialization operation.
Referencing old emails from the OMG dds4ccm mail list during the 2009-2010 timeframe, there were numerous discussions regarding the use of DDS read vs. take on reactive “push” vs. on-demand/polled “pull” extended port types and supporting interfaces. The result from that time was that the DDS_Listen and DDS_StateListen reactive extended port types that provide callback notification of newly received samples would utilize a take. This was ostensibly to help prevent typical user QoS configuration errors where read buffers within connectors using default QoS might fill up and consume excessive system resources, cause errors, etc. In contrast, the on-demand DDS_Read and DDS_Get ports implicitly do a read, rather than a take.
Note that the spec does not explicitly require the use of either read or take on any extended port or connector type. In fact it doesn’t say anything at all about underlying connector buffer management and associated semantics, aside from an implication that take should be used on reactive listen type ports due to their normal behavior of always delivering “fresh” data in callbacks, as well as the following note from section 18.104.22.168.2 page 14 of the spec that describes the “Interface Reader”:
"Note This interface is the basis for a passive data reader (i.e., a component that just looks at the data as they are). It is also very useful for the reactive data getters (i.e., components that need to react to new data, whether they choose to get them in pull mode or be notified in push mode) in their initialization phase. This is the reason why all the DDS ports on the subscribing side will embed a Reader basic port."
The assumption in this note that the Reader basic port interface on the DDS_Listen and DDS_StateListen reactive porttypes would only be useful for application layer initialization and subsequent duplication of the instanced state information flowing through the reader cache is what presumably led to their underlying assumed use of take. But again, this does not match our most common use case for the DDS_State connector in particular, where the reactive DDS_Listen and DDS_StateListen porttypes that offer the event notification callback also have the side-effect of destroying the reader cache with take vs. a read. This in turn renders their built-in Reader interfaces pretty useless for event-driven, run-time operation beyond the initialization phase of the component port’s lifecycle.
The apparent original use case in mind for the existing reactive subscriber port types was an application component that would utilize the connector capabilities for distributing and receiving new/updated/deleted keyed instance samples, consume these incoming samples once received with a take, and then require the user to duplicate the state table information at the application layer in a map-like state structure or a database of some variety. Per the note, the Reader interface was only envisioned as useful for initialization of application layer state tables, prior to turning on either the ONE_BY_ONE or MANY_BY_MANY listener mode callbacks.
We have a number of applications where we would like to receive event notifications for simple distributed state data on topics, with no required application layer state duplication, using a KEEP_LAST history QoS setting with small read buffer depth. In these applications, we would like to allow the latest samples for these instances to remain in the reader cache for run-time Reader query access by users, rather than having to copy and maintain them at the application layer instead.
We have exchanged a number of ideas with our CIAO support contractor Remedy IT on how we might best handle the use case of subscriber side event notification + distributed state query access. Our proposed extension to cover this common use case is captured in the three minor requested spec extensions below. This approach appears to have the least impact on existing implementations of DDS4CCM. Since this is a functionality extension vs. a change, it should not affect existing implementations that use the v1.1 interfaces and connector definitions, aside from the possible need for an additional empty callback stub in the language level component executor (which for us is auto-generated by the CIAO IDL compiler anyway).
1) Add a fourth DATA_AVAILABLE enumeration option to the existing “ListenerMode” enum definition, as defined in section 22.214.171.124.2 in the “Interface DataListenerControl” sub-section at the top of page 16 (26 of 72):
DATA_AVAILABLE // new mode setting for event notification + distributed state query
2) Add a new third callback operation called “on_data_available()” to the existing “Listener” interface definition, as defined in section 126.96.36.199.2 in the “Interface Listener” sub-section at the bottom of page 14 (24 of 72):
local interface Listener
void on_one_data (in T datum, in ReadInfo info);
void on_many_data (in TSeq data, in ReadInfoSeq infos);
void on_data_available(); // new callback operation for DATA_AVAILABLE mode
3) Add a new fifth callback operation called “on_data_available()” to the existing “StateListener” interface definition, as defined in section 188.8.131.52.2 in the “Interface StateListener” sub-section in the middle of page 15 (25 of 72):
local interface StateListener
void on_creation (in T datum, in ReadInfo info);
void on_one_update (in T datum, in ReadInfo info);
void on_many_updates (in TSeq data, in ReadInfoSeq infos);
void on_deletion (in T datum, in ReadInfo info);
void on_data_available(); // new callback operation for DATA_AVAILABLE mode
Functionally, a user wishing to support the event notification + distributed state query use case with DDS4CCM would first enable the DATA_AVAILABLE listener mode (after initialization) on the “data_control” basic port of either the DDS_Listen or DDS_StateListen extended port types instead of either the ONE_BY_ONE or MANY_BY_MANY mode as they do now.
Once DATA_AVAILABLE mode is enabled, the new on_data_available() callback would be invoked by the connector, in lieu of the other callback operations on the Listener or StateListener interfaces, when a new sample arrives on the topic. In this new listen mode, neither a DDS read nor take operation would be performed by the connector prior to the callback invocation, which is simply an event notification to the application component with no data passed. Within the application component’s on_data_available() implementation, the user is then free to utilize the existing Reader interface on these two reactive extended port types to query the state information in the underlying DDS reader cache, which should remain intact and accessible during post-initialization system operation.