2.2.1. RTI Connext DDS Core Libraries

The following issues affect backward compatibility in the Core Libraries starting in Release 6.1.0. Issues in the Core Libraries may affect components that use these libraries, including services and tools.

2.2.1.1. Configuration Changes

2.2.1.1.1. Property name typos are now errors, not warnings

Connext DDS 6.1.0 provides out-of-the-box stricter property validation than earlier releases. In the following XML configuration, the property ignore_sequence_bounds contains a typo:

<?xml version="1.0" encoding="UTF-8"?>
<dds xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:noNamespaceSchemaLocation="https://community.rti.com/schema/6.1.0/rti_dds_profiles.xsd">
   <qos_profile name="Example_Profile" base_name="BuiltinQosLib::Generic.StrictReliable">
      <datareader_qos>
         <property>
            <value>
               <element>
                  <name>dds.type_consistnecy.ignore_sequence_bounds</name>
                  <value>true</value>
               </element>
            </value>
         </property>
      </datareader_qos>
   </qosProfile>
</dds>

Previously, in 6.0.1, a typo in the name of a property within a well-known namespace was reported out-of-the-box as a warning, the property was ignored, and the creation of the entity was successful. For the example above, in 6.0.1 you would see the following:

[D0000|Sub(80000009)|T=Example MyType|CREATE Reader]
DDS_PropertyQosPolicy_validatePropertyNames:Unexpected property:
dds.type_consistnecy.ignore_sequence_bounds. Closest valid property:
dds.type_consistency.ignore_sequence_bounds

In 6.1.0, a typo in the name of a property within a well-known namespace is reported out-of-the-box as an error and the creation of the entity fails. For the example above, you will see the following:

[0x0101C928,0x1845FBA5,0xE53A39B9:0x80000009{E=Su,D=0}|CREATE DR WITH TOPIC Example MyType]
DDS_PropertyQosPolicy_validateEntityPropertyNames:Unexpected property:
dds.type_consistnecy.ignore_sequence_bounds. Closest valid property:
dds.type_consistency.ignore_sequence_bounds. If you wish to proceed with
this property name anyway, change
'dds.participant.property_validation_action' to 'VALIDATION_ACTION_SKIP' or
'VALIDATION_ACTION_WARNING'.
[0x0101C928,0x1845FBA5,0xE53A39B9:0x80000009{E=Su,D=0}|CREATE DR WITH TOPIC Example MyType]
DDS_DataReaderQos_is_consistentI:inconsistent QoS property
[0x0101C928,0x1845FBA5,0xE53A39B9:0x80000009{E=Su,D=0}|CREATE DR WITH TOPIC Example MyType]
DDS_Subscriber_create_datareader_disabledI:ERROR: Inconsistent QoS

You can go back to the 6.0.1 behavior where the typo is reported as a warning by setting the property dds.participant.property_validation_action to VALIDATION_ACTION_WARNING.

You can also go back to the 6.0.0 behavior where validation was skipped by setting the dds.participant.property_validation_action to VALIDATION_ACTION_SKIP.

The property dds.participant.property_validation_action accepts the following values:

  • VALIDATION_ACTION_EXCEPTION: Validate properties. Upon failure, log errors and fail.

  • VALIDATION_ACTION_WARNING: Validate properties. Upon failure, log warnings and do not fail.

  • VALIDATION_ACTION_EXCEPTION: Skip validation.

See PROPERTY QosPolicy, in the RTI Connext DDS Core Libraries User’s Manual for more information.

2.2.1.1.2. Error reported if load_plugin property not specified in properties of external plugin

Connext DDS 6.1.0 will report an error when parsing the properties of an external plugin (e.g., RTI Security Plugins) if the load_plugin property for the plugin is not defined. Consider the following example configuration for the Security Plugins:

<?xml version="1.0" encoding="UTF-8"?>
<dds xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:noNamespaceSchemaLocation="https://community.rti.com/schema/6.1.0/rti_dds_profiles.xsd">
   <qos_profile name="Example_Profile" base_name="BuiltinQosLib::Generic.StrictReliable">
      <domain_participant_qos>
         <property>
            <value>
               <element>
                  <name>com.rti.serv.secure.create_function</name>
                  <value>RTI_Security_PluginSuite_create</value>
               </element>
            </value>
         </property>
      </domain_participant_qos>
   </qosProfile>
</dds>

Even though the com.rti.serv.secure.create_function property is legal and it does not contain typos, in 6.1.0, you will see the following error when running with the above configuration, because the property com.rti.serv.load_plugin is not defined:

DDS_PropertyQosPolicy_validateEntityPropertyNames:Unexpected property:
com.rti.serv.secure.create_function. Closest valid property:
rti.monitor.create_function. If you wish to proceed with this property name
anyway, change 'dds.participant.property_validation_action' to
'VALIDATION_ACTION_SKIP' or 'VALIDATION_ACTION_WARNING'.
DDS_DomainParticipantQos_is_consistentI:inconsistent QoS property
DDS_DomainParticipantFactory_set_default_participant_qosI:ERROR: Inconsistent QoS
DDS_DomainParticipantFactory_load_profilesI:!set default DomainParticipant Qos
DDS_DomainParticipantFactory_create_participant_disabledI:ERROR: loading profiles

To fix the problem, make sure that the load_plugin property for the plugin is defined:

<?xml version="1.0" encoding="UTF-8"?>
<dds xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:noNamespaceSchemaLocation="https://community.rti.com/schema/6.1.0/rti_dds_profiles.xsd">
   <qos_profile name="Example_Profile" base_name="BuiltinQosLib::Generic.StrictReliable">
      <domain_participant_qos>
         <property>
            <value>
               <element>
                  <name>com.rti.serv.load_plugin</name>
                  <value>com.rti.serv.secure</value>
               </element>
               <element>
                  <name>com.rti.serv.secure.create_function</name>
                  <value>RTI_Security_PluginSuite_create</value>
               </element>
            </value>
         </property>
      </domain_participant_qos>
   </qosProfile>
</dds>

2.2.1.1.3. Instances no longer disposed by default when unregistered

The default value of autodispose_unregistered_instances in the WRITER_DATA_LIFECYCLE QoS Policy has changed from TRUE to FALSE. As a result, instances are no longer disposed by default when they are unregistered. Disposing an instance and unregistering from an instance are two distinct actions that a DataWriter can take. Therefore, in the majority of use cases, it is better and more transparent to explicitly perform each action when appropriate in your application rather than relying on Connext DDS to perform either action automatically.

If the new default of FALSE does not work for your application, set it to TRUE.

In addition, the autodispose_unregistered_instances setting no longer applies to a DataWriter deletion. See Section 2.2.1.8.1 for details.

2.2.1.1.4. Inconsistent QoS error when setting availability.enable_required_subscriptions to TRUE and history kind to KEEP_LAST on DataWriter

Setting enable_required_subscriptions in the AVAILABILITY QoS Policy now requires a history kind of KEEP_ALL. The reason is that not all samples can be guaranteed to be delivered to the required DataReaders if history kind is KEEP_LAST.

2.2.1.1.5. TYPE_CONSISTENCY_ENFORCEMENT QoS Policy has more permissive default values for ignore_sequence_bounds and ignore_string_bounds

The TYPE_CONSISTENCY_ENFORCEMENT QoS Policy has new default values for two of its boolean members: ignore_sequence_bounds and ignore_string_bounds. To comply with the OMG ‘Extensible and Dynamic Topic Types for DDS’ specification, version 1.3, the default values have changed from FALSE to TRUE.

As a result of this change, out of the box in 6.1.0, a DataWriter publishing a Topic with a type that contains a sequence member with a maximum bound ‘A’ will match with a DataReader subscribing to the same Topic using a type where the same sequence member has a smaller maximum bound.

Samples received by the DataReader will fail to be deserialized and be dropped if the number of elements in the sequence is larger than the maximum allowed by the DataReader type.

For example:

struct MyType1 {
    sequence<long, 100> m1;
}

struct MyType2 {
    sequence<long, 50> m1;
}

In earlier releases, a DataWriter publishing MyType1 and a DataReader subscribing to MyType2 did not match out of the box. In 6.1.0, the entities match. However, if the DataReader receives a sample where m1 has 8 elements, it will log a deserialization error and the sample will be reported as lost with the reason DDS_LOST_BY_DESERIALIZATION_FAILURE.

2.2.1.1.6. Removed refilter field in HISTORY QoS Policy

The refilter field in the HISTORY QoS Policy has been removed along with the associated public enum DDS_RefilterQosPolicyKind. If you are using this QoS setting, you will need to remove it from any source code and XML configuration files, and recompile your application.

The filtering behavior of a DataWriter can now only be controlled through the max_remote_reader_filters field in the DATA_WRITER_RESOURCE_LIMITS QoS Policy. The behavior of max_remote_reader_filters has not changed.

2.2.1.1.7. Deprecated transport.use_510_compatible_locator_kinds

The use_510_compatible_locator_kinds transport property was used to communicate over shared memory or UDPv6 between Connext DDS 5.2.0 (or later) and a previous release.

This property is deprecated in Connext DDS 6.1.0. Even though it is still supported, the new minimum_compatibility_version property is recommended. Set the value of minimum_compatibility_version to 5.1.0 to indicate that the transport should be compatible with Connext DDS 5.1.0.

2.2.1.2. API Changes

The following Application Program Interfaces (APIs) have been changed or deprecated in 6.1.0. For new APIs, see What’s New in 6.1.0.

See also Section 2.2.2 for Code Generator related changes.

2.2.1.2.1. Migrating to the new C# API

This release includes a new .NET Standard 2.0-compatible C# language binding (see Build applications for .NET 5 using new modern, multi-platform C# language binding, in What’s New in 6.1.0), which will replace the previous binding. The new C# binding has to be installed with an additional .rtipkg file.

The old binding is deprecated and will be removed in the next major release.

You should write new .NET components in your system using the new binding and consider migrating existing components. The old binding will still receive updates for critical issues, but won’t include new features or improvements.

The new binding has a few limitations in this first release, explained in the release notes.

2.2.1.2.1.1. Advantages of the new binding

The new C# binding offers a number of advantages with respect to the old one:

  • It is multi-platform (the old binding runs only on Windows®).

  • It runs on .NET 5 and other .NET Standard 2.0-compatible systems, not just .NET Framework.

  • It provides a modern and idiomatic C# API that uses common C# interfaces, patterns, and conventions.

  • It no longer requires compiling user types in C++/CLI; both the API and the generated code are C#.

  • The type and method documentation is included in the assembly and visible with IntelliSense.

  • It is distributed as a NuGet package, making it easier to use and deploy. The NuGet package transparently manages the native dependencies for the right target.

2.2.1.2.1.2. Migrating to the new binding

If you’re planning to move your .NET Framework applications to .NET 5, you will need to migrate to the new Connext DDS C# binding. The old one runs only on .NET Framework.

Even if you plan to continue using .NET Framework for now, you can start the migration. The new binding also supports .NET Framework 4.6.1-4.8, and both bindings can coexist within the same .NET assembly, so you can port your applications incrementally (you can’t, however, pass objects created by one API to methods of the other one). Like any other DDS application, applications using either binding will interoperate on the wire.

To start using the new binding in an existing code base, add the Rti.ConnextDds NuGet package to your .csproj files.

> dotnet add package Rti.ConnextDds

By default, the package is downloaded from nuget.org. This package requires a license to run your applications. To use the package from your Connext DDS installation, run the following command before dotnet add:

> dotnet nuget add source <installation dir>/lib/dotnet -n RTI

2.2.1.2.1.3. Tips for users of the old binding

There are a few key differences in the way you write your applications using the new and the old bindings. (This section is also helpful if you are familiar with the Connext DDS Java binding, which is similar to the old C# binding.)

  • Error reporting. The new binding reports errors exclusively as exceptions. In the old binding, some methods may report an error in the creation of some objects by returning null.

  • Object lifecycle. Both bindings use the factory pattern for Entity-derived objects. However, the way they are deleted is different:

    In the old binding, the factory type provided a delete_* method as well as a delete_contained_entities method when necessary:

    Listing 2.1 Object lifecycle in the old binding
    DomainParticipant participant = DomainParticipantFactory.get_instance().create_participant(0, ...);
    // ...
    Topic topic = participant.create_topic("HelloWorld", ...);
    // ...
    participant.delete_contained_entities();
    DomainParticipantFactory.get_instance().delete_participant(participant);
    

    In the new binding, types that can be explicitly deleted implement IDisposable, and their Dispose() method automatically deletes the contained entities if needed.

    Listing 2.2 Object lifecycle in the new binding (explicit Dispose call)
    DomainParticipant participant = DomainParticipantFactory.Instance.CreateParticipant(0);
    // ...
    Topic<Foo> topic = participant.CreateTopic<Foo>("HelloWorld");
    // ...
    participant.Dispose();
    
    Listing 2.3 Object lifecycle in the new binding (using block)
    using DomainParticipant participant = DomainParticipantFactory.Instance.CreateParticipant(0);
    // ...
    Topic<Foo> topic = participant.CreateTopic<Foo>("HelloWorld");
    // participant.Dispose() called when scope ends
    
  • Generic programming. The new binding uses generic classes. For example, in the new binding, a DataReader for the type Foo is DataReader<Foo>. In the old binding, this type was generated and called FooDataReader.

  • Type registration. The new binding registers data types automatically upon the creation of a Topic<T>. The old binding required a explicit call to FooTypeSupport.register_type(participant, typeName).

  • Status updates (listeners). The new API defines C# events for each Entity to notify of updates to each status. The old API provided listener interfaces that had to be implemented and attached to the Entity.

    This example compares how to handle two DataWriter statuses using each binding.

    Listing 2.4 Handling status updates with a listener in the old API
    class MyWriterListener : DataWriterListener
    {
        public override void on_publication_matched(DataWriter writer, ref PublicationMatchedStatus status)
        {
            // handle PublicationMatchedStatus update
        }
    
        public void on_offered_deadline_missed(DataWriter writer, ref OfferedDeadlineMissedStatus status)
        {
            // handle OfferedDeadlineMissedStatus update
        }
    }
    
    // ...
    
    var writer = publisher.create_datawriter(
        topic,
        Publisher.DATAWRITER_QOS_DEFAULT,
        null,
        StatusKind.STATUS_MASK_NONE);
    
    var listener = new MyWriterListener();
    writer.set_listener(
         listener,
         StatusKind.PUBLICATION_MATCHED_STATUS | StatusKind.OFFERED_DEADLINE_MISSED_STATUS);
    

    In the new API, the entity contains an event for each status that can receive updates:

    Listing 2.5 Handling status updates with event handlers in the new API
    var writer = publisher.CreateDataWriter(topic);
    writer.PublicationMatched += (writer, status) =>
    {
       // handle PublicationMatchedStatus update
    };
    writer.OfferedDeadlineMissed += (writer, status) =>
    {
       // handle OfferedDeadlineMissedStatus update
    };
    

    The old API allows setting the listener in the constructor. In the new API, the constructor receives a preEnableAction argument that allows performing an action on the entity being created right before it is enabled. This can be used to set the event handlers.

    Listing 2.6 Handling status updates with an event handler in the new API (in constructor)
    var writer = publisher.CreateDataWriter(
      topic,
      preEnableAction: writer =>
      {
          writer.PublicationMatched += OnPublicationMatched;
          writer.OfferedDeadlineMissed += OnOfferedDeadlineMissed;
      });
    
  • Reading data. The methods for reading data are significantly different.

    Compare the following code in the old API with the code in the new API that follows.

    Listing 2.7 Reading all available data using the old API
    FooSeq data_seq = new FooSeq();
    SampleInfoSeq info_seq = new SampleInfoSeq();
    
    try
    {
       reader.read( // or .take(
          sampleSeq,
          infoSeq,
          ResourceLimitsQosPolicy::LENGTH_UNLIMITED,
          SampleStateKind::ANY_SAMPLE_STATE,
          ViewStateKind::ANY_VIEW_STATE,
          InstanceStateKind::ANY_INSTANCE_STATE);
    
       for (int i = 0; i < sampleSeq.length; i++)
       {
          SampleInfo info = info_seq.get_at(i);
          if (!info.valid_data)
          {
             Foo data = data_seq.get_at(i);
             // use data
          }
    
       }
    
       reader.return_loan(sampleSeq, infoSeq);
    }
    catch(Retcode_NoData)
    {
    }
    

    In the new API, a single, IDisposable and IEnumerable collection provides the data and the info. When no data is available, the reader returns an empty collection instead of throwing an exception. In both bindings, the data is loaned. In the new binding, the loan is returned with Dispose() (here called automatically at the end of the scope of the using block), instead of return_loan().

    Listing 2.8 Reading all available data using the new API
    using (LoanedSamples<Foo> samples = reader.Read()) // or .Take()
    {
        foreach (LoanedSample<Foo> sample in samples)
        {
            if (sample.Info.ValidData)
            {
                Foo data = sample.Data;
                // use data
            }
        }
    }
    

    When the SampleInfo is not relevant, the code can be simplified further:

    Listing 2.9 Reading all available data using the new API (ignoring the SampleInfo)
    using (LoanedSamples<Foo> samples = reader.Read()) // or .Take()
    {
        foreach (Foo data in samples.ValidData())
        {
            // use data
        }
    }
    

    To copy the data, the generated data types provide a constructor, new Foo(data).

    In the new API, Read() and Take() receive no arguments. The method Select() allows specifying all the optional arguments. Select() replaces all the other variations of read and take in the old API. For example, instead of reader.take_w_condition(...), use reader.Select().WithCondition(...).Take().

    The new API also provides a new method, reader.TakeAsync(). This methods returns an IAsyncEnumerable that provides the data asynchronously as it is received.

    For more examples, in the API Reference, under Modules > Programming Snippets, select Subscription Examples and IDL examples.

  • Managing XML profiles. In the new binding, XML-defined QoS profiles, types, and applications are managed by the QosProvider class, instead of the DomainParticipantFactory.

    The QosProvider should also be used to create entities with an XML QoS profile.

    Listing 2.10 Creating a DataWriter with an XML profile with the old API
    var writer = publisher.create_datawriter_with_profile(
        topic,
        "MyQosLibrary",
        "MyQosProfile",
        null,
        StatusMask.STATUS_MASK_NONE);
    

    In the new API, you can use QosProvider.Default:

    Listing 2.11 Creating a DataWriter with an XML profile with the new API (default provider)
    var writerQos = QosProvider.Default.GetDataWriterQos("MyQosLibrary::MyQosProfile");
    var writer = publisher.CreateDataWriter(topic, writerQos);
    

    To configure which profiles are loaded by default, instead of using DomainParticipantFactoryQos.profile, use QosProvider.SetDefaultProviderParams().

    Or create a new QosProvider to load a specific file:

    Listing 2.12 Creating a DataWriter with an XML profile with the new API (custom provider)
    var qosProvider = new QosProvider("my_profiles.xml");
    var writerQos = qosProvider.GetDataWriterQos("MyQosLibrary::MyQosProfile");
    var writer = publisher.CreateDataWriter(topic, writerQos);
    
  • Immutable types. Some types in the new API are immutable and implement a “non-destructive mutation” pattern. All QoS types follow this pattern.

    This makes the syntax to configure a QoS policy quite different. Compare the code required to create a DataReader with two QoS policies using the old and the new binding.

    Listing 2.13 Configure QoS policies with the old binding
    var readerQos = new DataReaderQos();
    subscriber.get_default_datareader_qos(readerQos);
    readerQos.reliability.kind = ReliabilityQosPolicyKind.RELIABLE_RELIABILITY_QOS;
    readerQos.history.kind = HistoryQosPolicyKind.KEEP_LAST_HISTORY_QOS;
    readerQos.history.depth = 10;
    reader = subscriber.create_datareader(topic, readerQos, null, StatusMask.STATUS_MASK_NONE);
    

    In the new binding, each “edit” to a QoS object creates a new object that contains the values of the original object plus the edits.

    Listing 2.14 Configure QoS policies with the new binding
    var readerQos = subscriber.DefaultDataReaderQos
         .WithReliability(policy => policy.Kind = ReliabilityKind.Reliable)
         .WithHistory(policy =>
         {
            policy.Kind = HistoryKind.KeepLast;
            policy.Depth = 10;
         });
    
    var reader = subscriber.CreateDataReader(topic, readerQos);
    
  • Use of properties instead of getters or setters. The new binding prefers C# properties over getter/setter methods in most cases. You may find that a method in the old API (such as subscriber.get/set_default_datareader_qos()) is a property in the new API (subscriber.DefaultDataReaderQos)

    For more information, see the API Reference, under Modules > Programming Snippets > Entity Examples.

2.2.1.2.2. Warning for C++/CLI language option

This release includes a new C# language binding for .NET Standard 2.0 , which will replace the previous binding. The new C# binding has to be installed with an additional .rtipkg file. (See Section 2.2.1.2.1.)

Using the -language C# option without the additional package will continue to generate code for the old API, but will print a warning that the old binding will be removed in a future release.

When you install the new package, -language C# will stop printing the warning and use the new binding. (-language C++/CLI produces the same warning, but is not supported in the new API.)

2.2.1.2.3. Changes to SHMEM Transport APIs

The signature of the API that creates a new SHMEM transport instance in C has changed. It includes a new parameter called minimum_compatibility_version.

NDDS_Transport_Plugin* NDDS_Transport_Shmem_create(
      NDDS_Transport_Address_t *default_network_address_out,
      const struct DDS_PropertyQosPolicy *property_in,
      const struct DDS_ProductVersion_t *minimum_compatibility_version);

If you were calling NDDS_Transport_Shmem_create before, you must modify the function call to migrate your applications to 6.1.0. You must now add a third parameter, the minimum_compatibility_version.

The created shared memory transport plugin will be compatible with the Connext DDS version given in this parameter. Provide NULL as the argument to impose no compatibility restrictions. Doing so achieves the same behavior as in 6.0.0 and 6.0.1, where NDDS_Transport_Shmem_create did not have the minimum_compatibility_version parameter. To be compatible with releases earlier than 6.0.0, set the field to the version of the release that you want to be compatible with.

minimum_compatibility_version was added to support a new feature that allows capturing network traffic into a pcap file from a DomainParticipant. For more information on the new network capture feature in this release, see Network Capture in the RTI Connext DDS Core Libraries User’s Manual.

2.2.1.2.4. Modern C++ API: Constructor and listener setters behave as they used to, but you should use new APIs

Starting in this release, entities expect their listeners to be passed as a std::shared_ptr. Previously, listeners were expected as raw pointers.

Example of the new API:

class MyReaderListener : public dds::sub::DataReaderListener<Foo> {
    // …
} ;

// …

auto my_listener = std::make_shared<MyReaderListener>();
dds::sub::DataReader<Foo> reader(subscriber, topic, qos, my_listener);

This change simplifies the lifecycle of the listener and its entity. Previously, an entity with a listener was “retained” (it wouldn’t be automatically destroyed even if its reference count reached zero) to allow for the application to unset the listener and delete it.

Now an Entity with a listener holds a reference to the shared_ptr, keeping the listener alive while the Entity is alive. If the Entity reference count reaches zero, it is destroyed even if it has a listener.

The following APIs have changed:

  • Entity constructors now take a shared_ptr to the listener. Constructors taking a raw pointer are deprecated and may be removed in a future version.

  • New functions in each Entity called set_listener and get_listener have been added. They receive and return a shared_ptr to the listener. The previous functions that received and returned a raw pointer are deprecated and may be removed in a future version.

  • The rti::core::ListenerBinder utility is deprecated because it is no longer needed and may be removed in a future version.

    The deprecated constructor and listener setters behave as they used to (they prevent the automatic destruction of the entity), so existing code that upgrades to this version will not see any difference. However, it is recommended that applications transition to the new APIs.

2.2.1.2.5. Removed some enumerators from DDS_SampleRejectedStatusKind

In this release, you can identify why a subscribing application is not seeing samples using new statistics for lost, rejected, and dropped samples. See What’s New in 6.1.0

As a result of these changes, the following enumerators from SampleRejectedStatusKind have been removed:

  • DDS_REJECTED_BY_UNKNOWN_INSTANCE

  • DDS_REJECTED_BY_REMOTE_WRITERS_PER_SAMPLE_LIMIT

  • DDS_REJECTED_BY_VIRTUAL_WRITERS_LIMIT

  • DDS_REJECTED_BY_REMOTE_WRITERS_PER_INSTANCE_LIMIT

  • DDS_REJECTED_BY_REMOTE_WRITERS_LIMIT

If you are using any of these enumerators in your application, they will need to be removed and you will need to recompile your application.

2.2.1.2.6. DataWriter::get_matched_subscriptions and DataReader::get_matched_publications return not alive entities

Previously, the DDS::DataWriter::get_matched_subscriptions and DDS::DataReader::get_matched_publications APIs only returned instance handles for remote entities that were alive. This was not compliant with the OMG Data Distribution Service (DDS) standard API, version 1.4. Now, these APIs return the instance handles for any matching remote entities, including those that are not alive.

If you want to use the old behavior, where these APIs only returned instance handles for remote entities that were alive, use the APIs along with the new APIs DDS::DataWriter::is_matched_subscription_active() (to know which matched DataReaders are not active) and DDS::DataReader::is_matched_publication_alive() (to know which matched DataWriters are not alive).

2.2.1.2.7. Changed get_matched_publication_data and get_matched_subscription_data return value

DDS_DataWriter_get_matched_subscription_data and DDS_DataReader_get_matched_publication_data have changed their return value from DDS_RETCODE_PRECONDITION_NOT_MET to DDS_RETCODE_BAD_PARAMETER when the instance handle does not correspond to any matched endpoint. This change also affects APIs that use exceptions instead of return codes (Modern C++, Java, and .NET). The new return value is now consistent with the API documentation.

2.2.1.3. Library Size

The following table shows the different sizes of the main libraries in Connext DDS 6.1.0 versus 6.0.1, for a Linux architecture. The size of the libraries has increased due to the addition of new code; however, the changes are not significantly higher.

Note

The libraries tested are the release versions. The value for each of the libraries has been obtained as the text size displayed when using the size command on Linux.

Library

Size in 6.0.1

Size in 6.1.0

Traditional C++ API (libnddscpp)

1.49 MB

1.53 MB

Modern C++ API (libnddscpp2)

1 MB

1.14 MB

C API (libnddsc)

5.86 MB

6.23 MB

Core Library (libnddscore)

6.07 MB

6.57 MB

2.2.1.4. Memory Consumption

In general, 6.1.0 applications consume equivalent heap memory to 6.0.1.

Note

These numbers should be taken as a rough estimation due to the nature of how Connext DDS reserves memory.

Entity

6.0.1 Size

6.1.0 Size

Diff (Bytes)

Diff (%)

Participant Factory

74.4 KB

62.0 KB

-1,27 MB

-16.63

Participant

18,12 MB

1899.6 KB

0.00

0.00

Type

1.4 KB

1.4 KB

0.00

0.00

Topic

2.1 KB

1.9 KB

-218.00

-10.05

Subscriber

9.4 KB

9.4 KB

0.00

0.00

Publisher

3.7 KB

3.7 KB

0.00

0.00

DataReader

70.0 KB

70.0 KB

-7.00

-0.01

DataWriter

40.9 KB

40.9 KB

-14.00

-0.03

Instance

0.5 KB

0.5 KB

-12.00

-2.41

Sample

1.3 KB

1.3 KB

-7.00

-0.51

Remote Readers

7.2 KB

6.9 KB

-309.00

-4.22

Remote Writers

15.1 KB

15.1 KB

12.00

0.08

Reader Instance

876 Bytes

888 Bytes

12.00

1.37

Reader Samples

917 Bytes

917 Bytes

0.00

0.00

Remote Participant

75.3 KB

75.2 KB

-146.00

-0.19

2.2.1.5. Network Performance

In general, 6.1.0 applications have the same performance as in 6.0.1 for user data exchange. However, some significant performance and scalability improvements have been done in areas such as discovery and security. For detailed information on these improvements, see Section 2.2.1.6.

The following numbers are taken using RTI Perftest 3.1 for a Reliable scenario with unkeyed data.

  • Latency

    Sample Size (Bytes)

    Latency in 6.0.1 (microSec)

    Latency in 6.1.0 (microSec)

    Diff in microSec

    Diff in %

    32

    21.00

    21

    0.00

    0.00

    64

    21.00

    21

    0.00

    0.00

    128

    22.00

    22

    0.00

    0.00

    256

    22.00

    22

    0.00

    0.00

    512

    23.00

    23

    0.00

    0.00

    1 KB

    24.00

    25

    1.00

    4.17

    8 KB

    45.00

    45

    0.00

    0.00

    61.5 KB

    109.00

    109

    0.00

    0.00

    100 KB

    149.00

    150

    1.00

    0.67

    500 KB

    573.00

    575

    2.00

    0.35

    1 MB

    1007.00

    1008

    1.00

    0.10

    1.5 MB

    1668.00

    1668

    0.00

    0.00

    4 MB

    4110.00

    4114

    4.00

    0.10

    10 MB

    12704.00

    11091

    -1613.00

    -12.70

  • Throughput

    Sample Size (Bytes)

    Throughput in 6.0.1 (Mbps)

    Throughput in 6.1.0 (Mbps)

    Diff in Mbps

    Diff in %

    32

    1232.80

    1222.8

    -10.00

    -0.81

    64

    2196.50

    2219.0

    22.50

    1.02

    128

    3781.10

    3553.3

    -227.80

    -6.03

    256

    5770.70

    5621.7

    -149.00

    -2.58

    512

    7816.80

    7723.5

    -93.30

    -1.19

    1 KB

    9414.30

    9621.9

    207.60

    2.21

    8 KB

    9845.00

    9844.9

    -0.10

    -0.00

    61.5 KB

    9916.00

    9916.0

    0.00

    0.00

    100 KB

    9408.40

    9911.1

    502.70

    5.34

    500 KB

    9061.90

    9060.3

    -1.60

    -0.02

    1 MB

    8143.40

    8124.9

    -18.50

    -0.23

    1.5 MB

    8998.50

    9098.6

    100.10

    1.11

    4 MB

    7967.60

    8702.6

    735.00

    9.22

    10 MB

    7156.80

    8129.6

    972.80

    13.59

2.2.1.6. Discovery Performance

Participant Discovery and Endpoint Discovery times have improved in 6.1.0 compared to 6.0.1.

The following table displays an example of this improvement.

Note

This table shows the time to complete Endpoint Discovery based on the number of Endpoints. For each experiment (row), half the endpoints are DataReaders and half are DataWriters. Each Endpoint is assigned to a different Participant, and each Participant belongs to a separate process. All processes (and therefore all Participants and Endpoints) are deployed in a round-robin fashion across eight Linux nodes in an isolated lab. All nodes are connected through 1Gbps NICs to the same network.

Number of Endpoints

Discovery Time in 6.0.1 (Seconds)

Discovery Time in 6.1.0 (Seconds)

Diff (Seconds)

50

2.630

2.643

0.01

75

3.446

3.085

-0.36

100

4.011

3.333

-0.68

125

5.165

4.274

-0.89

150

6.148

5.241

-0.91

175

8.081

6.462

-1.62

200

9.589

7.177

-2.41

225

12.328

8.167

-4.16

250

17.073

9.971

-7.10

275

18.369

12.268

-6.10

300

21.289

13.923

-7.37

These improvements are not only extensive but even more pronounced when using RTI Security Plugins. See Section 2.2.4.10.

2.2.1.7. RTI Connext DDS Micro Compatibility

Connext DDS Micro does not interoperate with DataWriters that send compressed data. For more information about compression, see the DATA_REPRESENTATION QosPolicy section, in the RTI Connext DDS Core Libraries User’s Manual.

2.2.1.8. Miscellaneous

2.2.1.8.1. autodispose_unregistered_instances setting no longer applies when deleting DataWriter

In previous releases, the deletion of a reliable DataWriter where autodispose_unregistered_instances is set to TRUE may not have caused the DataWriter’s registered instances to transition to DDS_NOT_ALIVE_DISPOSED_INSTANCE_STATE on the reliable DataReader side. Instead, some instances may have transitioned to the DDS_NOT_ALIVE_NO_WRITERS state. To address this issue, DataWriter deletion is now treated differently than an explicit call to DataWriter::unregister_instance. Therefore, the autodispose_unregistered_instances setting no longer applies during DataWriter deletion and only applies when a DataWriter calls unregister_instance explicitly. Deletion of a DataWriter does not dispose of instances anymore, regardless of how autodispose_unregistered_instances is set.

In addition, the default value of autodispose_unregistered_instances has changed to FALSE. See Section 2.2.1.1.3 for additional details.

2.2.1.8.2. New Durable Writer History (database) schema

In 6.1.0, the schema of the storage files and tables created by a DataWriter using durable writer history to store DDS samples and instances has changed. Therefore, you cannot use the files and/or tables generated with previous releases.

If you have this requirement, contact RTI Support at support@rti.com.