Topic

A publisher or subscriber application creates topics in order to publish or subscribe to data elements with writer or reader objects. A topic can be viewed as a typed key-value dictionary where each key-value pair is a data element.

On this page:

Creation

A topic is an instance of the DataStorm::Topic class:

C++
template<typename Key, typename Value, typename UpdateTag=std::string> class Topic
{
    Topic(const Node& node, const std::string& name);
    ...
};

To construct a topic, you must provide a node and a name. For example:

C++
DataStorm::Node node(argc, argv);
DataStorm::Topic<string, float> topic(node, "temperatures");

The above creates a topic with a string key and float value named "temperatures".

Tip

You can also create a topic on the heap using std::make_shared, for example:

C++
auto topic = std::make_shared<DataStorm::Topic<string, float>>(node, "temperatures");

Coordination

The topic provides methods to coordinate with writers and readers attached to topics with the same name:

  • hasWriters, waitForWriters, waitForNoWriters
  • hasReaders, waitForReaders, waitForNoReaders

These methods allow the application to test or wait for readers or writers to connect or disconnect. For example, a writer can wait for readers to connect before it starts publishing samples by calling waitForReaders. Wait methods will raise NodeShutdownException if the node is shutdown.

Advertisement

The topic's creation does not trigger any network activity. It's only when the first reader or writer is created or when one of the coordination method is called that network activity occurs. Multicast UDP requests are sent to advertise the interest of the topic in reading or writing. Peers that receive the multicast requests will transparently establish a session with the advertised topic if they instantiate a topic with the same name. Once a session is established between two topics, they exchange information on their data writers and readers.

Filters

DataStorm supports two typed of filters:

  • key filters are used by readers to receive samples from data elements with keys matching a given criteria.
  • sample filters are used by readers to receive samples that match a given criteria.

Key and sample filters are defined on the topic.

Key filters

Key filters must be defined on both the topic used to create readers and the topic used to create writers. In other words, both the publisher and subscriber require the key filter implementation to filter keys.

While key filters are defined on the topic instance, they are not directly used by topics. The key filter implementation is used by the topic's writers or readers to filter keys based on a criteria which is defined upon creation of a filtered reader.

To register a key filter, the application must provide a filter name, a criteria type and a factory function that takes a criteria parameter and returns another function that takes the key and returns true if the key is accepted or false otherwise.

For example, to register a key filter that only accepts keys starting with a given string, you can register the following key filter:

C++
DataStorm::Topic<string, float> topic(node, "temperatures");
topic.setKeyFilter<string>("startswith", [](const string& prefix)
{
    return [prefix](const string& key)
    {
        return key.size() >= prefix.size() && key.compare(0, prefix.size(), prefix) == 0;
    };
}); 

The criteria type is specified with the setKeyFilter template parameter (a string in the example above).

Sample filters

Contrary to key filters, sample filters are only defined on the topic used to create writers.

Sample filters are used by the topic's writers to filter samples based on a criteria which is provided upon creation of a filtered reader. 

To register a sample filter, the application must provide a filter name, a criteria type and a factory function that takes a criteria parameter and returns another function that takes the sample and returns true if the sample is accepted or false otherwise.

For example, to register a sample filter that only accepts samples with temperature values inferior to a given limit:

C++
DataStorm::Topic<string, float> topic(node, "temperatures");
topic.setSampleFilter<float>("inferior", [](float limit)
{
    return [limit](const Sample<string, float>& sample)
    {
        return sample.getValue() < limit;
    };
}); 

The criteria type is specified with the setSampleFilter template parameter (a float in the example above).

Predefined filters

DataStorm provides two predefined filters with the reserved names _regex and _event.

The _regex filter accepts a string criteria that defines the regular expression used to filter the key or sample value. This filter can be used both as a key and optionally as a sample filter if the value can be converted to a string with the ostream << operator.

The _event filter applies only to samples and can be used to only receive samples with a given event data member (Add, Remove, Update, ...).

Updaters

An application can register updaters with the topic to use partial updates. Instead of writing the whole value, a writer can write a partial update.

The partial update is used by registered updaters to compute the new value. Updaters must be registered with both the topic used to create writers and the topic used to create readers. In other words, both the publisher and subscriber side need to be able to compute a new value given a partial update.

An updater is a function that accepts two parameters: the current value and the partial update value. It returns the new value based on these two parameters.

For example, to register an updater that increments the temperature value, the application can register an "increment" updater:

C++
DataStorm::Topic<string, float> topic(node, "temperatures");
topic.setUpdater<int>("increment", [](float& temperature, int v)
{
    temperature += v;
}); 

The setUpdater template parameter specifies the type of the partial update value. In the example above, it's an int.

The increment string is the update tag. By default, update tags are specified as strings. This is fine for most applications but for applications that prefer to minimize network usage, they can consider using another type. The update tag type can be customized with the third template parameter of the topic template. For example, it could use a short update tag instead:

C++
const short IncrementTag = 1;
DataStorm::Topic<string, float, short> topic(node, "temperatures");
topic.setUpdater<int>(IncrementTag, [](float& temperature, int v)
{
    temperature += v;
});