4.5. Tutorials

4.5.1. Example: Getting Started with Replay and Shapes Demo

Start by recording Square data, as described in Section 3.5.1.

4.5.1.1. Edit the Replay Configuration

In your <RTI_WORKSPACE>/user_config/recording_service directory, edit the USER_REPLAY_SERVICE.xml file. Change the storage_format to be JSON_SQLITE.

<?xml version="1.0" encoding="UTF-8"?>
<!-- All of our files start with a dds tag -->
<dds xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:noNamespaceSchemaLocation="http://community.rti.com/schema/6.0.0/rti_replay_service.xsd">

    <replay_service name="UserReplayService">

        <storage>
            <sqlite>
                <storage_format>JSON_SQLITE</storage_format>
                <!-- No <database_dir> specified means current directory -->
            </sqlite>
        </storage>

        <!-- Optionally select the begin and end times for the data to be
             replayed -->
        <!--data_selection>
            <time_range>
                <begin_time>
                    <sec>0</sec>
                    <nanosec>0</nanosec>
                </begin_time>
            </time_range>
        </data_selection-->

        <!-- Specify playback behavior, including what local time to start -->
        <!--playback>
        </playback-->

        <!-- Configuration for the service:
        DomainParticipant configuration, storage configuration -->
        <domain_participant name="DefaultParticipant">
            <domain_id>0</domain_id>
        </domain_participant>

        <session name="DefaultSession"
                 default_participant_ref="DefaultParticipant">

            <!-- Topics to replay in this session -->
            <topic_group name="DefaultTopicGroup">
                <!-- Topics to replay -->
                <allow_topic_name_filter>*</allow_topic_name_filter>
                <deny_topic_name_filter>rti/*</deny_topic_name_filter>
            </topic_group>
        </session>
    </replay_service>
</dds>

4.5.1.2. Start Shapes Demo and Subscribe to Squares

Start Shapes Demo from the Launcher tool and create a Square subscriber as described in Section 3.5.1.

Create a Shapes Demo subscriber

4.5.1.3. Start Replay Service

Start Replay Service:

<NDDSHOME>/bin/rtireplayservice -cfgName UserReplayService -verbosity 3

You should see Square data replayed in Shapes Demo.

4.5.2. Example: Replaying Data at a Different Rate

To replay data at a faster or slower rate than it was recorded, you can edit the configuration file to specify a playback rate.

Start by recording Square data as described in Section 3.5.1.

4.5.2.1. Edit the Replay Configuration

In your <RTI_WORKSPACE>/user_config/recording_service directory, edit the USER_REPLAY_SERVICE.xml file. Add a playback rate, as seen in the following XML:

<?xml version="1.0" encoding="UTF-8"?>

<!-- All of our files start with a dds tag -->
<dds xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:noNamespaceSchemaLocation="https://community.rti.com/schema/6.0.0/rti_replay_service.xsd">

  <replay_service name="UserReplayServiceJson">
      <!-- This will look for files in the directory 'json_recording' in the
           current working directory. This is integrated with the Recording
           Service configuration 'UserRecorderServiceJson' in the file
           USER_RECORDING_SERVICE.xml -->
      <storage>
          <sqlite>
              <storage_format>JSON_SQLITE</storage_format>
              <database_dir>json_recording</database_dir>
          </sqlite>
      </storage>

      <!-- Optionally select the begin and end times for the data to be
           replayed -->
      <!--data_selection>
          <time_range>
              <begin_time>
                  <sec>0</sec>
                  <nanosec>0</nanosec>
              </begin_time>
          </time_range>
      </data_selection-->

      <!-- Specify playback behavior, including what local time to start -->
      <playback>
          <rate>2</rate>
      </playback>

      <domain_participant name="DefaultParticipant">
          <domain_id>0</domain_id>
      </domain_participant>

      <session name="DefaultSession"
               default_participant_ref="DefaultParticipant">
          <!-- Topics to replay in this session -->
          <topic_group name="DefaultTopicGroup">
              <!-- Topics to replay -->
              <allow_topic_name_filter>*</allow_topic_name_filter>
              <deny_topic_name_filter>rti/*</deny_topic_name_filter>
          </topic_group>
      </session>
  </replay_service>
</dds>

4.5.2.2. Start Shapes Demo

Start Shapes Demo from the Launcher tool and create a Square subscriber.

Create a Shapes Demo subscriber

4.5.2.3. Start Replay Service

Start Replay Service:

<NDDSHOME>/bin/rtireplayservice -cfgName UserReplayService -verbosity 3

You should see Square data replayed in Shapes Demo twice as fast as it was originally recorded.

4.5.3. Example: Plugging in Custom Storage

If you created a storage plugin to record data into your own custom storage, you can also create a plugin to replay from that same storage.

Note

The APIs for custom storage are not available in the Basic bundle.

There are full examples written in C and C++ about plugging in custom storage in Recording Service, in the RTI Community Recording Service examples: C storage plugin and RTI Community Recording Service examples: C++ storage plugin.

4.5.3.1. Custom Storage API Overview

To retrieve data for replay, you must implement the following APIs:

  • A create storage reader API:
    • This is used to create a StorageReader object.
    • This API is a C function. In C++, you can use macros to declare and define the C function for your class. For example:
      • RTI_RECORDING_STORAGE_READER_CREATE_DECL(FileStorageReader)
      • RTI_RECORDING_STORAGE_READER_CREATE_DEF(FileStorageReader)
    • The StorageReader is used to create and delete StorageStreamInfoReaders and StorageStreamReaders.
  • StorageReader:
    • A create stream info reader API, where you create a stream reader that provides information about what streams (topics) are in your storage.
    • A delete stream info reader API, where you delete a stream info reader
    • A create stream reader API, where you create a stream reader
    • A delete stream reader API, where you delete a stream reader
  • StorageStreamInfoReader:
    • Read: An API to retrieve discovery data from the storage. It uses a selector object to determine the kind of samples (not read or any kind) to be returned, as well as the time range. The samples should be returned in increasing time-stamp order.
    • Return loan: An API that notifies the plugin that it can release resources associated with the data passed to the read API
    • Get service start time: An API to query the recorded time from which to start replaying
    • Get service stop time: An API to query the recorded time at which to stop replaying
    • Finished: An API to tell Replay Service and Converter that there are no more stream infos to read.
    • Reset: An API called by the Replay Service to tell the plug-in to reset its state because it is looping. After this method is called, the stream reader should be ready to start reading data from the beginning of the stream, again.
  • StorageStreamReader
    • Read: An API to retreive data from storage. It uses a selector object to determine the kind of samples (not read or any kind) to be returned, as well as the time range. The samples should be returned in increasing time-stamp order.
    • Return loan: An API that notifies the plugin that it can release resources associated with the data passed to the take API
    • Finished: An API that notifies the plugin that there is no more data in this data stream

The APIs provide a mechanism to have strongly-typed StorageStreamReader classes and a builtin one is provided based on dds::core::xtypes::DynamicData.

More detailed API documentation is located in:

4.5.4. Using Timestamp Tags with Replay Service

If your recording was originally made with the builtin SQLite storage plugin, and you used the tag_timestamp remote command to tag certain events, then your recording contains timestamp tags: symbolic timestamp names you can use in place of timestamps expressed in units of time. For more information on timestamp tags, see Section 3.5.6.

You can list the timestamp tags that are in your recorded database by using the rtirecordingservice_list_tags script. Use the -d argument to point to the directory that contains your recorded database, as follows:

<NDDSHOME>/bin/rtirecordingservice_list_tags -d /database/directory/

This command will analyze the recording in /database/directory/ and list the details of any timestamp tags in the recording, including the tag names, descriptions, and associated timestamps.

You can use the tag_name of the timestamp tags you find in a recording when you are creating an XML configuration file for Replay Service by using the <data_selection> tag.

For example, if after running rtirecordingservice_list_tags, you see output such as:

tag_name                    timestamp_ms   tag_description
--------------------------  -------------  ------------------------
/my_example/my_events/tag1  1546484663309  first tag description
/my_example/my_events/tag2  1546484703360  a second tag description

Then you can have a <data_selection> tag in your XML for Replay Service, after the <storage> tag, that looks like the following:

<data_selection>
    <time_range>
        <begin_tag>/my_example/my_events/tag1</begin_tag>
        <end_tag>/my_example/my_events/tag2</end_tag>
    </time_range>
</data_selection>

Replay will replay data between those tags. Note that when expressing a <time_range> tag, you can mix and match timestamps and timestamp tags. For example, you can use a <begin_tag> (by referring to a tag_name) to express the time when replay should begin, and an <end_tag> with an end time timestamp (expressed in time units) to express when replay should end. If you do not provide one of the bounds, then the start of recording is the default begin bound and the end of recording is the default end bound.