2.3 Type-Consistency Enforcement

The DataReader's TypeConsistencyEnforcementQosPolicy defines the rules that determine whether the type used to publish a given topic is consistent with the type used to subscribe to it.

Note: If the type information is not available for a topic (and force_type_validation is false), these rules do not apply.

The QosPolicy structure includes the members in the following table.

Table 2.5 DDS_TypeConsistencyEnforcementQosPolicy

Type

Field Name

Description

DDS_TypeConsistencyKind

kind

Can be any of the following values:

  • AUTO_TYPE_COERCION (default)
  • ALLOW_TYPE_COERCION
  • DISALLOW_TYPE_COERCION

See below for details.

DDS_Boolean

ignore_sequence_bounds

Controls whether sequence bounds are taken into consideration for type assignability.

If false, a DataWriter’s type containing a sequence with a larger maximum length will not be assigned to a DataReader’s type containing a sequence with a smaller maximum length. Since the types are not assignable, the DataReader will not match when type information is available.

If true, a sequence in a DataReader's type can have a maximum length smaller than that of a sequence in a DataWriter's type. The types will be assignable, and the DataReader will match; however, when the length of the sequence in a particular DataWriter's sample is larger than the DataReader's maximum length, that sample is discarded. See "Verifying Sample Consistency: Sample Assignability" in the Core Libraries Extensible Types Guide.

Default: true

DDS_Boolean

ignore_string_bounds

Controls whether string bounds are taken into consideration for type assignability.

If false, then a DataWriter’s type containing a string with a larger maximum length will not be assigned to a DataReader’s type containing a string with a smaller maximum length. Since the types are not assignable, the DataReader will not match when type information is available.

If true, then a string in a DataReader’s type can have a maximum length smaller than that of a string in a DataWriter’s type. They are assignable, and the DataReader will match; however, when the length of the string in a particular DataWriter’s sample is larger than the DataReader’s maximum length, that sample is discarded. See "Verifying Sample Consistency: Sample Assignability" in the Core Libraries Extensible Types Guide.

Default: true

DDS_Boolean

ignore_member_names

Controls whether member names are taken into consideration for type assignability.

If false, types containing members with the same ID and different names are not assignable to each other. Since the types are not assignable, the DataReader will not match when type information is available.

If true, members of a type can change their name while keeping their member ID. For example, MyType and MyTypeSpanish are only assignable if ignore_member_names is true:

 
struct MyType {
    @id(10) int32 x;
    @id(20) int32 angle;
};
struct MyTypeSpanish {
    @id(10) int32 x;
    @id(20) int32 angulo;
};

Since the types are assignable, the DataReader will match.

Default: false

DDS_Boolean

prevent_type_widening

Controls whether type widening is allowed. A type T2 widens a type T1 when T2 contains required members that are not present in T1.

If a DataReader of T2 sets prevent_type_widening to true, then the DataReader will not be matched with a DataWriter of T1 with fewer members because T1 is not assignable to T2.

If a DataReader of T2 sets prevent_type_widening to false, then the DataReader will match with the DataWriter of T1. The DataReader will assume a value for members in T2 that are not in T1. See "Prevent Type Widening" below.

Default: false

DDS_Boolean

force_type_validation

Controls whether type information must be available in order to complete matching between a DataWriter and this DataReader.

If false, matching may occur as long as the type names match. Note that if the types have the same name, but the types are not assignable, DataReaders may fail to deserialize incoming data samples. If force_type_validation is true and no type information is available, then the DataReader will not match.

Default: false

DDS_Boolean

ignore_enum_literal_names

Controls whether enumeration constant names are taken into consideration for type assignability. If the option is set to true, then enumeration constants may change their names, but not their values, and still maintain type assignability. If the option is set to false, then in order for enumerations to be assignable, any constant that has the same value in both enumerations must also have the same name. For example, enum Color {RED = 0} and enum Color {ROJO = 0} are assignable if and only if ignore_enum_literal_names is true.

Default: false

This QoSPolicy defines a type consistency kind, which allows applications to choose to either allow or disallow data type matching:

  • AUTO_TYPE_COERCION (default): For a regular DataReader, this default value is translated to ALLOW_TYPE_COERCION. For a Zero Copy DataReader, this default value is translated to DISALLOW_TYPE_COERCION. (See the "Zero Copy Transfer Over Shared Memory" section in the RTI Connext Core Libraries User's Manual for information on why a Zero Copy DataReader requires the DISALLOW_TYPE_COERCION option.)
  • DISALLOW_TYPE_COERCION: The DataWriter and DataReader must support the same data type in order for them to communicate. (This is the degree of enforcement required by the OMG DDS Specification prior to the OMG ‘Extensible and Dynamic Topic Types for DDS’ Specification.)
  • ALLOW_TYPE_COERCION: The DataWriter and DataReader need not support the same data type in order for them to communicate as long as the DataReader’s type is assignable from the DataWriter’s type. The concept of assignability is explained in 2.2 Verifying Type Consistency: Type Assignability.

This policy applies only to DataReaders; it does not have request-offer semantics. The value of the policy cannot be changed after the DataReader has been enabled.

The default enforcement kind is AUTO_TYPE_COERCION. This default kind translates to ALLOW_TYPE_COERCION, except in the following cases:

  • For a Zero Copy DataReader whose topic type does not use FLAT_DATA language binding, the kind is translated to DISALLOW_TYPE_COERCION.
  • When the middleware is introspecting the built-in topic data declaration of a remote DataReader in order to determine whether it can match with a local DataWriter, if it observes that no TypeConsistencyEnforcementQosPolicy value is provided (as would be the case when communicating with a Service implementation not in conformance with this specification), it assumes a kind of DISALLOW_TYPE_COERCION.

2.3.1 Rules For Type-Consistency Enforcement

The type-consistency enforcement rules consist of two steps applied on the DataWriter and DataReader side:

  • Step 1. If both the DataWriter and DataReader specify a TypeObject, it is considered first. If the DataReader allows type coercion, then its type must be assignable from the DataWriter’s type, taking into account the values of prevent_type_widening, ignore_sequence_bounds, ignore_string_bounds, ignore_member_names, and ignore_enum_literal_names. If the DataReader does not allow type coercion, then its type must be equivalent to the type of the DataWriter.
  • Step 2. If either the DataWriter or the DataReader does not provide a TypeObject definition, then the registered type names are examined. The DataReader’s and DataWriter’s registered type names must match exactly, as was true in Connext releases prior to 5.0. This step will fail if force_type_validation is true, regardless of the type names.

If either Step 1 or Step 2 fails, the Topics associated with the DataReader and DataWriter are considered to be inconsistent (see 2.5 Notification of Inconsistencies: INCONSISTENT_TOPIC Status).

2.3.2 Prevent Type Widening

The prevent_type_widening field determines whether type widening is allowed. In Figure 2.1: prevent_type_widening = false, VehicleData_v2 has three members and VehicleData_v1 two members. With type widening allowed, the narrower car (VehicleData_v1, with two members) can write to the wider car (VehicleData_v2), but notice that the DataReader assumes a value that might be misleading (in this case, a default speed of zero).

Figure 2.1: prevent_type_widening = false

If widening is not allowed (Figure 2.2: prevent_type_widening = true), VehicleData_v1 and VehicleData_v2 do not communicate with each other.

Figure 2.2: prevent_type_widening = true

2.3.3 Type Assignability Properties

The properties in Table 2.6 Type Assignability Properties relax some of the rules in the standard type-assignability algorithm. These properties can be set in the QoS of the DataReader, DataWriter, and DomainParticipant (in this case all DataReaders and DataWriters created by that DomainParticipant inherit the property). By default they are disabled.

Table 2.6 Type Assignability Properties

Property Name

Description

dds.sample_assignability.accept_unknown_union_discriminator

This property can take the following values:

  • 0 (default value): Received samples containing a union discriminator value that selects a union member on the DataWriter but not on the DataReader are dropped.
  • 1: Received samples containing a union discriminator value that selects a union member on the DataWriter but not on the DataReader are set to the default union value on the DataReader.

    Note:
    The default union value is a union with the discriminator set to select the default member, if one is defined, or otherwise to the lowest value associated with any member. In addition, the value of that member is set to the default value for its corresponding type.
  • 2: Received samples containing a union discriminator value that selects a union member on the DataWriter but not on the DataReader preserve the discriminator value and do not select any union member on the DataReader.

Received samples containing a union discriminator value that do not select a union member on the DataWriter always preserve the discriminator value on the DataReader with accept_unknown_union_discriminator set to 1 or 2, unless the union discriminator value is an enumerator which is not valid on the DataReader’s type. In this case, the union is set to its default value.

Assume the following two types:

Publisher Type:

@mutable
union MyUnion switch(int32) {
    case 0:
	int32 m1;
    case 1:
	int16 m2;
    case 2:
	double m3;
}; 

Subscriber Type:

@mutable
union MyUnion switch(int32) {
    case 0: 
	int32 m1;
    case 1:
	int16 m2;
}; 

When this property, accept_unknown_union_discriminator, is set to 0, if the DataWriter sends a union with the discriminator set to 2, the DataReader will fail deserializing the sample and will drop it.

When this property is set to 1, the DataReader application will the set the sample to its default value, which has the discriminator set to 0 and member m1 set to the default value for an int32, which is 0.

When this property is set to 2, the DataReader application will deserialize a sample where the discriminator is set to 2 and where there is no member of the union (m1 or m2) selected.

You can set this property as part of the Property QoS for either the DomainParticipant or the DataReader. If it is set in both the DomainParticipant and DataReader, the value in the DataReader's QoS will be applied.

This functionality is supported both in generated code as well as when using the DynamicData API. However, if you use the value 2, there is no API in DynamicData to obtain the discriminator value if it does not select a union member.

dds.sample_assignability.accept_unknown_enum_value

When set to 1, samples containing an unknown enumerator can be successfully deserialized to the default enumeration value. For example, given the following two types:

Publisher Type:

enum MyEnum {
    ONE = 1,
    TWO = 2,
    THREE = 3
};
struct MyType {
    MyEnum m1;
};

Subscriber Type:

enum MyEnum {
    ONE = 1,
    TWO = 2
};
struct MyType {
    MyEnum m1;
};

By default, if the DataWriter sends m1 = THREE, the DataReader cannot deserialize the sample. However if this property is set to 1 then the Subscribing application will receive a sample with m1 = ONE. The default enumeration value is defined as the first declared member of the enumeration.

You can set this property as part of the Property QoS for either the DomainParticipant or the DataReader. If it is set in both the DomainParticipant and DataReader, the value in the DataReader's QoS will be applied.

This functionality is supported both in generated code as well as when using the DynamicData API.

dds.type_consistency.ignore_member_names

This property has been replaced with ignore_member_names and ignore_enum_literal_names in the TypeConsistencyEnforcementQosPolicy (see 2.3 Type-Consistency Enforcement), but is still supported for compatibility with previous releases. If this property is set, its value supersedes the values in the QosPolicy.

dds.type_consistency.ignore_sequence_bounds

This property has been replaced with ignore_sequence_bounds and ignore_string_bounds in the TypeConsistencyEnforcementQosPolicy (see 2.3 Type-Consistency Enforcement), but is still supported for compatibility with previous releases. If this property is set, its value supersedes the values in the QosPolicy.