Creating Custom Content Filters
[Programming How-To's]

Working with custom content filters. More...

Introduction

By default, RTI Data Distribution Service creates content filters with the DDS_SQL_FILTER, which implements a superset of the DDS-specified SQL WHERE clause. However, in many cases this filter may not be what you want. Some examples are:

This HOWTO explains how to write your own custom filter and is divided into the following sections:

The Custom Content Filter API

A custom content filter is created by calling the DDSDomainParticipant::register_contentfilter function with a DDSContentFilter that contains a compile, an evaluate function and a finalize function. DDSContentFilteredTopic can be created with DDSDomainParticipant::create_contentfilteredtopic_with_filter to use this filter.

A custom content filter is used by RTI Data Distribution Service at the following times during the life-time of a DDSContentFilteredTopic (the function called is shown in parenthesis).

The compile function

The compile function is used to compile a filter expression and expression parameters. Please note that the term compile is intentionally loosely defined. It is up to the user to decide what this function should do and return.

See DDSContentFilter::compile for details.

The evaluate function

The evaluate function is called each time a sample is received to determine if a sample should be filtered out and discarded.

See DDSContentFilter::evaluate for details.

The finalize function

The finalize function is called when an instance of the custom content filter is no longer needed. When this function is called, it is safe to free all resources used by this particular instance of the custom content filter.

See DDSContentFilter::finalize for details.

Example Using C format strings

Assume that you have a type Foo.

You want to write a custom filter function that will drop all samples where the value of Foo.x > x and x is a value determined by an expression parameter. The filter will only be used to filter samples of type Foo.

Writing the Compile Function

The first thing to note is that we can ignore the filter expression, since we already know what the expression is. The second is that x is a parameter that can be changed. By using this information, the compile function is very easy to implement. Simply return the parameter string. This string will then be passed to the evaluate function every time a sample of this type is filtered.

Below is the entire compile function.

DDS_ReturnCode_t MyContentFilter::compile(
    void** new_compile_data, const char * /* expression */,
    const DDS_StringSeq& parameters,const DDS_TypeCode* /* type_code */,
    const char * /* type_class_name */,
    void * /* old_compile_data */) {

    *new_compile_data = (void*)DDS_String_dup(parameters[0]);

    return DDS_RETCODE_OK;
}

Writing the Evaluate Function

The next step is to implement the evaluate function. The evaluate function receives the parameter string with the actual value to test against. Thus the evaluate function must read the actual value from the parameter string before evaluating the expression. Below is the entire evaluate function.

DDS_Boolean MyContentFilter::evaluate(
    void* compile_data,const void* sample) {

    char *parameter = (char*)compile_data;
    DDS_Long x;

    Foo *foo_sample = (Foo*)sample;

    sscanf(parameter,"%d",&x);

    return (foo_sample->x > x ? DDS_BOOLEAN_FALSE : DDS_BOOLEAN_TRUE);
}

Writing the Finalize Function

The last function to write is the finalize function. It is safe to free all resources used by this particular instance of the custom content filter that is allocated in compile. Below is the entire finalize function.

void MyContentFilter::finalize(
    void* compile_data) {
    /* free parameter string from compile function */
    DDS_String_free((char *)compile_data);
}

Registering the Filter

Before the custom filter can be used, it must be registered with RTI Data Distribution Service:

    DDSDomainParticipant *myParticipant=NULL;

    /* myParticipant = .... */

    DDSContentFilter *myCustomFilter = new MyContentFilter();

    if (myParticipant->register_contentfilter(
        (char*)"MyCustomFilter",
        myCustomFilter) != DDS_RETCODE_OK) {
        printf("Failed to register custom filter\n");
    }

Unregistering the Filter

When the filter is no longer needed, it can be unregistered from RTI Data Distribution Service:

    DDSDomainParticipant *myParticipant = NULL;

    /* myParticipant = .... */

    DDSContentFilter *myCustomFilter =
        myParticipant->lookup_contentfilter((char*)"MyCustomFilter");

    if (myCustomFilter != NULL) {
        if (myParticipant->unregister_contentfilter(
            (char*)"MyCustomFilter") != DDS_RETCODE_OK) {
            printf("Failed to unregister custom filter\n");
        }

        delete myCustomFilter;
    }

RTI Data Distribution Service C++ API Version 4.5e Copyright © 23 Oct 2011 Real-Time Innovations, Inc