10.1. Creating an XML profiles file
An XML file can contain several XML profiles.
These XML profiles are defined within the <dds>
element, and in turn, within the <profiles>
XML elements.
The possible topologies for the definition of XML profiles are specified in Rooted vs Standalone profiles definition.
It is worth mentioning that the first element of the xml profile must have the xmlns
attribute with the link
xmlns="http://www.eprosima.com"
, in both rooted or standalone definitions.
That link defines the reference of the xsd
schema that the xml
document complies with.
The available profile types are:
Log profiles, and
The following sections will show implementation examples for each of these profiles.
<?xml version="1.0" encoding="UTF-8" ?>
<dds xmlns="http://www.eprosima.com">
<profiles>
<domainparticipant_factory profile_name="domainparticipant_factory_profile">
<!-- ... -->
</domainparticipant_factory>
<participant profile_name="participant_profile">
<!-- ... -->
</participant>
<data_writer profile_name="datawriter_profile">
<!-- ... -->
</data_writer>
<data_reader profile_name="datareader_profile">
<!-- ... -->
</data_reader>
<topic profile_name="topic_profile">
<!-- ... -->
</topic>
<transport_descriptors>
<!-- ... -->
</transport_descriptors>
</profiles>
<library_settings>
<!-- ... -->
</library_settings>
<log>
<!-- ... -->
</log>
<types>
<!-- ... -->
</types>
</dds>
Note
The Example section shows an XML file with all the possible configurations and profile types. This example is useful as a quick reference to look for a particular property and how to use it. The Fast DDS XSD scheme can be used as a quick reference too.
10.1.1. Loading and applying profiles
In case the user defines the Entity
profiles via XML files, it is required to load these
XML files using the load_XML_profiles_file()
public member function before creating any
entity.
It is also possible to load directly the XML information as a string data buffer using the
load_XML_profiles_string()
public member function.
Moreover, create_participant_with_profile()
,
create_publisher_with_profile()
, create_subscriber_with_profile()
,
create_datawriter_with_profile()
, and create_datareader_with_profile()
member functions expect a profile name as an argument.
Fast DDS searches the given profile name over all the loaded XML profiles, applying the profile to the entity
if founded.
if (RETCODE_OK ==
DomainParticipantFactory::get_instance()->load_XML_profiles_file("my_profiles.xml"))
{
DomainParticipant* participant =
DomainParticipantFactory::get_instance()->create_participant_with_profile(
0, "participant_xml_profile");
Topic* topic =
participant->create_topic("TopicName", "DataTypeName", TOPIC_QOS_DEFAULT);
Publisher* publisher = participant->create_publisher_with_profile("publisher_xml_profile");
DataWriter* datawriter = publisher->create_datawriter_with_profile(topic, "datawriter_xml_profile");
Subscriber* subscriber = participant->create_subscriber_with_profile("subscriber_xml_profile");
DataReader* datareader = subscriber->create_datareader_with_profile(topic, "datareader_xml_profile");
}
// Load XML as string data buffer
std::string xml_profile =
"\
<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\
<dds>\
<profiles xmlns=\"http://www.eprosima.com\" >\
<data_writer profile_name=\"test_datawriter_profile\" is_default_profile=\"true\">\
<qos>\
<durability>\
<kind>TRANSIENT_LOCAL</kind>\
</durability>\
</qos>\
</data_writer>\
</profiles>\
</dds>\
";
if (RETCODE_OK ==
DomainParticipantFactory::get_instance()->load_XML_profiles_string(xml_profile.c_str(),
xml_profile.length()))
{
// Create DDS entities with profiles
}
For simplicity, the create_participant_with_default_profile()
method takes the default
profile set in the environment to create a participant.
It requires the XML profile to have been already loaded.
Please, refer to XML profiles for further information regarding loading profiles.
Warning
It is worth mentioning that if the same XML profile file is loaded multiple times, the second loading of the file will result in an error together with the consequent error log.
Note
To load dynamic types from XML files see the Loading XML Types profile in Fast DDS application subsection of Dynamic Types profiles.
10.1.2. Get QoS from raw XML profiles
Although the standard procedure is to first load XML profiles, and then create entities given the profile name of choice, it is also possible to get the desired QoS from the XML profile directly so it can be modified before being used. For this purpose, the following public methods are available:
For each qos
kind there exists two method versions; with and without profile_name
argument.
When provided, the method searches for the given profile name in the loaded XML profiles,
and results in error if not found.
When not provided, the method fills the provided qos
object with the first retrieved profile of the
pertinent kind, and results in error when none found.
In addition, there exists another method version which looks for the default profile of the pertinent kind
in the provided XML string.
Following is an example of how to get the QoS from a raw XML profile and modify it before creating a new entity.
DomainParticipant* participant =
DomainParticipantFactory::get_instance()->create_participant(0, PARTICIPANT_QOS_DEFAULT);
Topic* topic =
participant->create_topic("TopicName", "DataTypeName", TOPIC_QOS_DEFAULT);
Publisher* publisher = participant->create_publisher(PUBLISHER_QOS_DEFAULT);
// Load XML as string data buffer
std::string xml_profile =
"\
<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\
<dds>\
<profiles xmlns=\"http://www.eprosima.com\" >\
<data_writer profile_name=\"test_datawriter_profile\" is_default_profile=\"true\">\
<qos>\
<durability>\
<kind>TRANSIENT_LOCAL</kind>\
</durability>\
</qos>\
</data_writer>\
</profiles>\
</dds>\
";
// Extract Qos from XML
DataWriterQos qos;
if (RETCODE_OK == publisher->get_datawriter_qos_from_xml(xml_profile, qos, "test_datawriter_profile"))
{
// Modify extracted qos and use it to create DDS entities
}
10.1.3. Rooted vs Standalone profiles definition
Fast DDS offers various options for the definition of XML profiles. These options are:
Stand-alone: The element defining the XML profile is the root element of the XML file. Elements
<dds>
,<profiles>
,<library_settings>
,<types>
, and<log>
can be defined in a stand-alone manner.Rooted: The element defining the XML profile is the child element of another element. For example, the
<participant>
,<data_reader>
,<data_writer>
,<topic>
, and<transport_descriptors>
elements must be defined as child elements of the<profiles>
element.
The following is an example of the definition of the <types>
XML profile using the two previously discussed
approaches.
Stand-alone |
<?xml version="1.0" encoding="UTF-8" ?>
<types xmlns="http://www.eprosima.com">
<type>
<!-- Type definition -->
</type>
<type>
<!-- Type definition -->
<!-- Type definition -->
</type>
</types>
|
Rooted |
<?xml version="1.0" encoding="UTF-8" ?>
<dds xmlns="http://www.eprosima.com">
<types>
<type>
<!-- Type definition -->
</type>
<type>
<!-- Type definition -->
<!-- Type definition -->
</type>
</types>
</dds>
|
Note
Make sure that the first element of the xml profile must have the xmlns
tag with the link
xmlns="http://www.eprosima.com"
, in both rooted or standalone definitions.
10.1.4. Modifying predefined XML profiles
Some scenarios may require to modify some of the QoS after loading the XML profiles. For such cases the Types of Entities which act as factories provide methods to get the QoS from the XML profile. This allows the user to read and modify predefined XML profiles before applying them to a new entity.
if (RETCODE_OK ==
DomainParticipantFactory::get_instance()->load_XML_profiles_file("my_profiles.xml"))
{
DomainParticipantQos participant_qos;
DomainParticipantFactory::get_instance()->get_participant_qos_from_profile(
"participant_xml_profile",
participant_qos);
// Name obtained in another section of the code
participant_qos.name() = custom_name;
// Modify number of preallocations (this overrides the one set in the XML profile)
participant_qos.allocation().send_buffers.preallocated_number = 10;
// Create participant using the modified XML Qos
DomainParticipant* participant =
DomainParticipantFactory::get_instance()->create_participant(
0, participant_qos);
}
10.1.5. Dynamic content by leveraging environment variables
For deployment scenarios that require part of the XML content to be dynamically generated, Fast DDS supports using
environment variables on the text content of any XML tag.
The format for environment variables expansion is ${ENV_VAR_NAME}
, where ENV_VAR_NAME
follows the restrictions
from IEEE 1003.1:
Note
Environment variable names … consist solely of uppercase letters, digits, and the ‘_’ (underscore) from the characters defined in Portable Character Set and do not begin with a digit.
More than one environment variable can be used, and they can be mixed with literal text.
The expansion will take place when the XML file is loaded, so changing the value of an environment variable afterwards will have no effect.
The following is an example of an XML allowing a participant to exclusively communicate with the participants on a
fixed IP address, taken from REMOTE_IP_ADDRESS
environment variable.
It also gives the participant a name that mixes literal text with the content from two environment variables.
<?xml version="1.0" encoding="UTF-8" ?>
<dds xmlns="http://www.eprosima.com">
<profiles>
<participant profile_name="env_var_parsing_example">
<rtps>
<name>This is app '${MY_APP_NAME}' running on host '${MY_HOST_NAME}'</name>
<builtin>
<initialPeersList>
<locator>
<udpv4>
<address>${REMOTE_IP_ADDRESS}</address>
</udpv4>
</locator>
</initialPeersList>
</builtin>
</rtps>
</participant>
</profiles>
</dds>
Warning
The Fast DDS XSD schema does not support the environment variables expansion feature, so validation of an XML file with environment variables expansion expressions will fail.