Filtering during the exchange process is performed by a DDSContentFilteredTopic, which is created by the DDSDataReader as a way of specifying a subset of the data samples that it wishes to receive.
Filtering samples that have already been received by the DDSDataReader is performed by creating a DDSQueryCondition, which can then used to check for matching samples, be alerted when matching samples arrive, or retrieve matching samples through use of the FooDataReader::read_w_condition or FooDataReader::take_w_condition functions. (Conditions may also be used with the APIs FooDataReader::read_next_instance_w_condition and FooDataReader::take_next_instance_w_condition.)
Filtering may be performed on any topic, either keyed or un-keyed, except the Built-in Topics. Filtering may be perfomed on any field, subset of fields, or combination of fields, subject only to the limitations of the filter syntax, and some restrictions against filtering some sparse value types of the Dynamic Data API.
RTI Data Distribution Service contains built in support for filtering using SQL syntax, described in the Queries and Filters Syntax module.
filter_expression
and expression_parameters
, futher specifies the values of the data which the DDSDataReader wishes to receive.Custom filters may also be constructed and utilized as described in the Creating Custom Content Filters module.
Once the DDSContentFilteredTopic has been created, a DDSDataReader can be created using the filtered topic. The filter's characteristics are exchanged between the DDSDataReader and any matching DDSDataWriter during the discovery processs.
If the DDSDataWriter allows (by DDS_DataWriterResourceLimitsQosPolicy::max_remote_reader_filters) and the number of filtered DDSDataReader is less than or equal to 32, and the DDSDataReader 's is empty, then the DDSDataWriter will performing filtering and send to the DDSDataReader only those samples that meet the filtering criteria.
If disallowed by the DDSDataWriter, or if more than 32 DDSDataReader require filtering, or the DDSDataReader has set the , then the DDSDataWriter sends all samples to the DDSDataReader, and the DDSDataReader discards any samples that do not meet the filtering criteria.
Although the filter_expression
cannot be changed once the DDSContentFilteredTopic has been created, the expression_parameters
can be modified using DDSContentFilteredTopic::set_expression_parameters. Any changes made to the filtering criteria by means of DDSContentFilteredTopic::set_expression_parameters, will be conveyed to any connected DDSDataWriter. New samples will be subject to the modified filtering criteria, but samples that have already been accepted or rejected are unaffected. However, if the DDSDataReader connects to a DDSDataWriter that re-sends its data, the re-sent samples will be subjected to the new filtering criteria.
DDSQueryCondition may be created on a disabled DDSDataReader, or after the DDSDataReader has been enabled. If the DDSDataReader is enabled, and has already recevied and stored samples in its queue, then all data samples in the are filtered against the DDSQueryCondition filter criteria at the time that the DDSQueryCondition is created. (Note that an exclusive lock is held on the DDSDataReader sample queue for the duration of the DDSQueryCondition creation).
Once created, incoming samples are filtered against all DDSQueryCondition filter criteria at the time of their arrival and storage into the DDSDataReader queue.
The number of DDSQueryCondition filters that an individual DDSDataReader may create is set by DDS_DataReaderResourceLimitsQosPolicy::max_query_condition_filters, to an upper maximum of 32.
Foo:
DDS_ContentFilteredTopic *cft = NULL; DDS_StringSeq parameters(2); const char* cft_param_list[] = {"1", "100"}; cft_parameters.from_array(cft_param_list, 2); cft = participant->create_contentfilteredtopic("ContentFilteredTopic", Foo_topic, "value > %0 AND value < %1", cft_parameters); if (cft == NULL) { printf("create_contentfilteredtopic error\n"); subscriber_shutdown(participant); return -1; }
DDSDataReader *reader = NULL; reader = subscriber->create_datareader(cft, datareader_qos, // or DDS_DATAREADER_QOS_DEFAULT reader_listener, // or NULL DDS_STATUS_MASK_ALL); if (reader == NULL) { printf("create_datareader error\n"); subscriber_shutdown(participant); return -1; } FooDataReader *Foo_reader = FooDataReader::narrow(reader); if (Foo_reader == NULL) { printf("DataReader narrow error\n"); subscriber_shutdown(participant); return -1; }
cft->get_expression_parameters(cft_parameters); DDS_String_free(cft_parameters[0]); DDS_String_free(cft_parameters[1]); cft_parameters[0] = DDS_String_dup("5"); cft_arameters[1] = DDS_String_dup("9"); retcode = cft->set_expression_parameters(cft_arameters); if (retcode != DDS_RETCODE_OK) { printf("set_expression_parameters error\n"); subscriber_shutdown(participant); return -1; }
DDSDataReader *reader = ...; FooDataReader *Foo_reader = FooDataReader::narrow(reader);
DDSQueryCondition *queryCondition = NULL; DDS_StringSeq qc_parameters(2); const char *qc_param_list[] = {"0","100"}; qc_parameters.from_array(qc_param_list,2); queryCondition = reader->create_querycondition(DDS_NOT_READ_SAMPLE_STATE, DDS_ANY_VIEW_STATE, DDS_ALIVE_INSTANCE_STATE, "value > %0 AND value < %1", qc_parameters); if (queryCondition == NULL) { printf("create_query_condition error\n"); goto error_exit; }
FooSeq data_seq; DDS_SampleInfoSeq info_seq; retcode = Foo_reader->read_w_condition(data_seq, info_seq, DDS_LENGTH_UNLIMITED, queryCondition); if (retcode == DDS_RETCODE_NO_DATA) { printf("no matching data\n"); } else if (retcode != DDS_RETCODE_OK) { printf("read_w_condition error %d\n", retcode); subscriber_shutdown(participant); return -1; } else { for (i = 0; i < data_seq.length(); ++i) { if (info_seq[i].valid_data) { /* process your data here */ } retcode = Foo_reader->return_loan(data_seq, info_seq); if (retcode != DDS_RETCODE_OK) { printf("return loan error %d\n", retcode); subscriber_shutdown(participant); return -1; } }
retcode = reader->delete_readcondition(queryCondition);
This optimization applies to all filtering using the built-in SQL filter, performed by the DDSDataReader, for either DDSContentFilteredTopic or DDSQueryCondition. This does not apply to filtering perfomed for DDSContentFilteredTopic by the DDSDataWriter.