12.1. Configuring RTI Services
RTI Services are configured using XML and offer multiple ways to load the configurations. The loading alternatives are in general standard across all RTI Services. This section covers how you can provide XML configurations to RTI Services, as well as specific behaviors on how the XML is parsed, validated, and interpreted.
12.1.1. How to Load and Select an XML Configuration
To run an RTI Service with a specific configuration you need to provide two pieces:
XML content with one or more configurations
This is the actual XML code that contains the service-specific configurations. We refer to this as the input XML document. There are two different input sources: File system or in-memory strings.Configuration name
The name of the actual service configuration to be run. Each RTI Service defines a top-level element that shall contain aname
attribute that uniquely identifies it.
12.1.1.1. Loading from Files
RTI Services can receive a list of file paths separated by semicolons (;
):
filepath_1;filepath_2; ... filepath_N
File paths can be relative or absolute and files are loaded in order from left to right. How you provide the file path list depends on whether you run the service from the shipped executable or embed it into your application using the Library API [1].
Use the -cfgFile
option.
Warning
On some operating systems, ;
is interpreted as a command separator, so
you will need to escape the path list with double quotes "
.
For example on Linux systems:
$NDDSHOME/bin/rtiroutingservice -cfgFile "file.xml;/home/file2.xml"
$NDDSHOME/bin/rtirecordingservice -cfgFile "file.xml;/home/file2.xml"
$NDDSHOME/bin/rticlouddiscoveryservice -cfgFile "file.xml;/home/file2.xml"
where [NDDSHOME]
indicates the path to your Connext installation.
Set the ServiceProperty::cfg_file
member.
For example in C++:
ServiceProperty property; property.cfg_file("file.xml;/home/file2.xml"); ... Service service(property);
12.1.1.2. Loading from In-Memory Strings
If you are embedding RTI Services into your application using the
Library API, the input XML document can be also be provided through a
string array object. You can do so by setting the
ServiceProperty::cfg_strings
member.
For example in C++:
std::vector<std::string> xml_strings;
xml_strings.resize(2);
/* This sample demonstrates using Routing Service */
xml_strings[0] = "<dds><routing_service name=\"MyService\">";
xml_strings[1] = "</routing_service></dds>";
property.cfg_strings(xml_strings);
...
Service service(property);
12.1.1.3. Selecting which Configuration to Run
As stated earlier, the input XML document may contain one or more service configurations. You will need to select which specific configuration to run by providing its configuration name.
How you provide the configuration name depends on whether you run the service from the shipped executable or by embedding it into your application using the Library API.
For example, consider the following input XML document in a file named
MyService.xml
that contains two configurations.
<dds>
<routing_service name="Service1"> ... </routing_service>
<routing_service name="Service2"> ... </routing_service>
</dds>
<dds>
<recording_service name="Service1"> ... </recording_service>
<recording_service name="Service2"> ... </recording_service>
</dds>
<dds>
<cloud_discovery_service name="Service1"> ... </cloud_discovery_service>
<cloud_discovery_service name="Service2"> ... </cloud_discovery_service>
</dds>
You can run the configuration for Service1
as follows:
Use the -cfgName
option.
For example, on Linux systems:
$NDDSHOME/bin/rtiroutingservice -cfgFile MyService.xml -cfgName Service1
$NDDSHOME/bin/rtirecordingservice -cfgFile MyService.xml -cfgName Service1
$NDDSHOME/bin/rticlouddiscoveryservice -cfgFile MyService.xml -cfgName Service1
Set the ServiceProperty::cfg_name
member.
For example in C++:
ServiceProperty property; property.cfg_file("MyService.xml"); property.cfg_name("Service1"); ... Service service(property);
12.1.1.4. Default Files
In addition to manually providing input XML files, RTI Services also attempt to automatically load a set of files from predefined locations:
File |
Allowed Content |
---|---|
|
|
|
|
|
|
where [SERVICE]
refers to the concrete product name in uppercase.
For example:
ROUTING_SERVICE
for RTI Routing ServiceRECORDING_SERVICE
for RTI Recording ServiceCLOUD_DISCOVERY_SERVICE
for RTI Cloud Discovery Service
These files are loaded only if present.
You can disable the loading of default files by using the proper option:
Use the -skipDefaultFiles
option.
Set the ServiceProperty::skip_default_files
member to true.
12.1.1.5. XML Syntax and Validation
The XML representation of DDS-related resources must follow these syntax rules:
It shall be a well-formed XML document according to the criteria defined in clause 2.1 of the Extensible Markup Language standard.
It shall use UTF-8 character encoding for XML elements and values.
It shall use
<dds>
as the root tag of every document.
To validate the loaded configuration, each RTI Service relies on an XSD document that describes the format of the XML content. The validation of the input XML document occurs after all the files and strings have been parsed. If the validation fails, the RTI Service will fail to load the XML and log an error. For example here is an error in the case of RTI Cloud Discovery Service:
NDDSHOME/bin/rticlouddiscoveryservice
[/cloud_discovery_services/default|CREATE] line 26: Element 'invalid_example_tag': This element is not expected.
[/cloud_discovery_services/default|CREATE] CDSService_loadConfiguration:!validate configuration
[/cloud_discovery_services/default|CREATE] CDSService_initialize:!load configuration
[/cloud_discovery_services/default|CREATE] CDSService_new:!init service
main:!create service
You can disable the XSD validation process by using the proper option:
Use the -ignoreXsdValidation
option.
Set the ServiceProperty::enforce_xsd_validation
member to false.
We recommend including a reference to this document in the XML file that contains the service’s configuration; this provides helpful features in code editors such as Visual Studio®, Eclipse®, and NetBeans®, including validation and auto-completion while you are editing the XML file.
The XSD for the RTI Service configuration elements is in
[NDDSHOME]/resource/schema/rti_[service_name].xsd
, where [service_name]
refers to product name in lower snake case. For example:
routing_service
for RTI Routing Servicerecording_service
for RTI Recording Servicecloud_discovery_service
for RTI Cloud Discovery Service
To include a reference to the XSD document in your XML file, use the attribute
xsi:noNamespaceSchemaLocation
in the <dds>
tag. For example:
<?xml version="1.0" encoding="UTF-8"?>
<dds xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="[NDDSHOME]/resource/schema/rti_routing_service.xsd">
<!-- ... -->
</dds>
Warning
The product XSD file provided under [NDDSHOME]/resource/schema
is to
assist you in the process of creating an XML configuration document.
RTI Services have the XSD builtin in memory, so making modifications to
the reference XSD will not have an impact on the validation process.
12.1.1.6. Listing Available Configurations
The shipped executables of some RTI Services provide an option to list
all the available configurations in the specified input XML document. You
can run the service with the -listConfig
option to list the available
configurations and exit. For example, on Linux systems:
rtiroutingservice -listConfig
Available configurations:
- default:([NDDSHOME]/resource/xml/RTI_ROUTING_SERVICE.xml)
Routes all topics from domain 0 to domain 1
- defaultBothWays:([NDDSHOME]/resource/xml/RTI_ROUTING_SERVICE.xml)
Routes all topics from domain 0 to domain 1 and the other way around
- defaultReliable:([NDDSHOME]/resource/xml/RTI_ROUTING_SERVICE.xml)
Routes all topics from domain 0 to domain 1 using reliable communication
rticlouddiscoveryservice -listConfig
Available configurations:
- rti.cds.builtin.config.default:(builtin string)
Empty configuration. Assumes default values.
- rti.cds.builtin.config.default_wan:(builtin string)
Enables Real-Time WAN Transport.
XML variables:
- RTI_CDS_PORT: CDS public and host port number
- RTI_CDS_PUBLIC_ADDR: CDS WAN public address
Each listed configuration indicates the input source (file path or string)
and the content of the <documentation>
tag if present. This operation lists
all the configurations detected from the specified input XML document from all
the locations and files.
12.1.1.7. Configuration Variables
The builtin XML parser of the RTI Service offers a special mechanism to reuse and customize content at runtime through the concept of Configuration variables.
A configuration variable is an RTI-specific construct that you can use in the input XML documents to set placeholders for content that will be expanded at parsing time. A variable is specified as follows:
$(VAR_NAME)
where VAR_NAME
is the name that identifies the variable. You can use
configuration variables in your XML content as an attribute value and element
text.
<element attribute="$(VAR_ATTR)">my expanded $(VAR_TEXT)</element>
The possible ways a variable can be expanded are listed below in precedence order:
Process environment.
export VAR_NAME=my_value
Using a specific option when running the service.
Use the
-DVAR_NAME=VALUE
option$<rtiservicename> ... -DVAR_NAME=my_value
where
<rtiservicename>
is one ofrtiroutingservice
,rtirecordingservice
orrticlouddiscoveryservice
.Set the
ServiceProperty::user_environment
memberServiceProperty property; property.user_environment()["VAR_NAME"] = "var_value"; ...
<configuration_variables>
section, which represents an unbounded list of variable name-value value pairs.<configuration_variables> <value> <element> <name>VAR_NAME</name> <value>var_value</value> </element> ... </value> </configuration_variables>
All three of these mechanisms can be used in combination or separately. For the above example, you could expand one variable using the process environment and another variable using the command-line option. The following command:
export VAR_ATTR=expanded_attr
<rtiservicename> ... -DVAR_TEXT=expanded_text
where <rtiservicename>
is one of rtiroutingservice
,
rtirecordingservice
or rticlouddiscoveryservice
, will result in the
following actual parsed XML with the expanded variables:
<element attribute="expanded_attr">my expanded expanded_text</element>
If the RTI Service cannot expand a variable, it will load the XML document and log an error indicating which variable could not be expanded. Here is an example for RTI Routing Service:
[/routing_services/default|CREATE] RTIXMLUTILSVariableExpansor_expandString:variable with name=ADMIN_DOMAIN_ID not defined
[/routing_services/default|CREATE] RTIXMLUTILSVariableExpansor_visit:!parse at line=19 for tag=domain_id: expand environment variable in element text
[/routing_services/default|CREATE] ROUTERXmlVariableExpansor_visit:!parse at line=19 for tag=domain_id
...
12.1.2. How to Load Default QoS Profiles
Generally, loading a default QoS profile follows the same mechanism as Connext applications. The details on how to specify default QoS profiles in XML is explained in the section Overwriting Default QoS in the RTI Connext Core Libraries User’s Manual.
In short, you will need to mark a profile as the default using the is_default_qos
attribute. For RTI Services, you will need to do this as part of the default file
USER_QOS_PROFILES.xml
(see Default Files).
This requirement is necessary since the default QoS profiles are parsed by the
underlying DomainParticipantFactory and not the service itself.
Warning
Marking as default a QoS profile defined in a different file than
USER_QOS_PROFILES.xml
will have no effect.
12.1.3. How to Set Logging Properties
You can configure different aspects of the logging infrastructure that is part of RTI Services and Connext. This section describes different ways to set these logging properties.
12.1.3.1. Command-Line Options
The shipped executable for an RTI Service typically offers some out-of-the-box options to configure logging. Typically, you will find these options:
-verbosity
sets the verbosity level for the messages generated by the service and Connext.-logFormat
configures the format of the log messages, such as whether they contain timestamps, thread IDs, etc.-logFile
redirects the logging to a specified text file.
You can refer to the Usage
section of each individual product user’s manual
for further details.
12.1.3.2. Library API
To configure the service-level verbosity, use the Logger
singleton
class part of the Library API. For example, the following sets
WARNING
level for the service logs in RTI Routing Service. For other
services change the preceding rti::routing
prefix to match the RTI Service
you are working with.
rti::routing::Logger::instance().service_verbosity(
rti::config::Verbosity::WARNING);
To configure the Connext-level verbosity (for logs generated by the DDS
libraries), you can use the Connext configuration logger API. For example,
the following sets WARNING
level for the Connext logs:
rti::config::Logger::instance().verbosity(
rti::config::Verbosity::WARNING);
For the remaining overall logging properties, such as the log format, output file, and so on, you can also use the Connext configuration logger API. For example, to redirect the logging to an output file:
rti::config::Logger::instance().output_file(my_service_logs.txt);
12.1.3.3. XML Configuration
As an alternative to the previous two methods, you can configure some logging
properties through the LoggingQosPolicy
which can be specified in XML.
For more information, see the
LOGGING QosPolicy (DDS Extension)
in the RTI Connext Core Libraries User’s Manual.
The Logging QoS is configured within the <participant_factory_qos>
that
is part of a QoS profile. Since multiple profiles can be present in the loaded
XML document, to tell Connext which one to use, you will need to mark the
profile as the default using the is_default_qos
attribute, or for the
DomainParticipantFactory, the is_default_participant_factory_profile
attribute.
See How to Load Default QoS Profiles for details on how to load default QoS
profiles with RTI Services. For example, you can set different properties
for the logger by placing the XML code seen below in the USER_QOS_PROFILES.xml
default file:
<dds>
<qos_library name="DefaultLibrary">
<qos_profile name="DefaultProfile" is_default_participant_factory_profile ="true">
<participant_factory_qos>
<logging>
<!-- this element affects Connext logs only -->
<verbosity>ALL</verbosity>
<!-- for all Connext and Service logs -->
<category>ENTITIES</category>
<print_format>MAXIMAL</print_format>
<output_file>LoggerOutput1.txt</output_file>
</logging>
</participant_factory_qos>
</qos_profile>
</qos_library>
</dds>
See also
- Configuring Connext Logging
Describes the types of logging messages and how to use the logger to enable them.
- Identifying Threads used by Connext DDS
Describes the logging messages that provide thread-context information.
12.1.4. How to Run as an Operating System Daemon
Certain Operating Systems offer the capability to run processes in the background and non-interactively. On Linux or macOS systems, this is referred to as daemon processes. On Windows systems, this is referred to as a service.
How to run a process as a daemon depends on the OS and in some cases there are multiple options. This section describes the most common way to run an RTI Service as a daemon of the main OS.
12.1.4.1. Linux and macOS Systems
The simplest and more portable way requires you to use the Library API to
create your own executable that instantiates the RTI Service and sets the
running process as a daemon using the daemon()
API. For example, for
RTI Routing Service:
#include <stdlib.h>
#include "rti/routing/Service.hpp"
int main(int argc, char **argv)
{
using namespace rti::routing;
if (daemon(0,0)) {
Logger::instance().error("Failed to create daemon process\n");
return -1;
}
// parse arguments and configure ServiceProperty
ServiceProperty property;
property.cfg_file(argv[1]);
...
Service service(property);
service.start();
}
The above code generates an executable that runs the process as a daemon with
zero-value arguments, indicating that the working directory is /
and the
standard output is redirected to /dev/null
. You can find more information
about the daemon()
in the user man pages.
Note that if you link the application dynamically, you will need to guarantee that the dependency libraries are available as part of the library path. An alternative is to link the applications statically.
12.1.4.2. Windows Systems
To run a process as a Windows Service we recommend using the third party tool Non-Sucking Service Manager (NSSM). This tool allows you to run an existing executable as a service, while adjusting environment variables and command-line arguments.
Hence you can use NSSM to run the shipped executable of an RTI Service. For example, for Routing Service you can run:
nssm install myRouterService <rtiroutingservice> "-cfgName default"
The above command will install a service named myRouterService
on your
Windows system that runs Routing Service with the default configuration. Then you can
manage the service with the nssm
GUI utility itself or the Windows
Services Control Manager (select Control Panel -> Administrative Services -> Services).
The example above causes the service to use the executable directory as the working
directory and relies on the default configuration file in [NDDSHOME]/resource/xml
.
You can specify a different working directory as well as different command-line
arguments as follows:
nssm set myRouterService AppDirectory <my_working_dir>
nssm set myRouterService AppParameters "-cfgFile my_router.xml -cfgName MyRoute"
Alternatively, you can use the Library API to embed the RTI Service into your own executable and implement the Windows Library APIs to run the executable as a Windows Service. (see How to: Create Windows Services).
Here are some things to consider when running an RTI Service as a Windows Service:
All
AppParameters
arguments must be enclosed in quotation marks.If you specify
-cfgFile
in the Start Parameters field, you must use the full path to the file.Some versions of Windows do not allow Windows Services to communicate with other services/applications using shared memory. In such case, you will need to disable the shared memory transport in all DomainParticipants created by the RTI Service.
In some scenarios, you may need to add a multicast address to your discovery peers or simply use RTI Cloud Discovery Service.
12.1.5. How to use a License File with RTI Services
If your RTI Connext distribution requires a license file, you will receive one
from RTI via email. To install the license file, follow the instructions in
Installing RTI Connext DDS, in the RTI Connext DDS Installation Guide.
Alternatively, you can provide the RTI Service with the path to your license
file using either the -licenseFile
command-line argument or the
license_file_name
field in the Service Property of the Library API.
Note
Some RTI Services do not require a license file.
Check the command line arguments list for the RTI Service to see if a
-licenseFile
argument exists. If it doesn’t, you can use the RTI Service
without a license file.
Each time your RTI Service starts, it looks for the license file in the following locations, in order, until it finds a valid license:
The file specified in the environment variable
RTI_LICENSE_FILE
, which you may set to point to the full path of the license file, including the filename. For example, on Linux:export RTI_LICENSE_FILE=/home/username/my_rti_license.dat
The file
rti_license.dat
in the current working directory.The file
rti_license.dat
in the directory specified by the environment variableNDDSHOME
.
12.1.6. Key Terms
- XML document
The input XML contained within the
<dds>
root, which contains one or more configurations for an RTI Service.- Configuration name
Unique identification of a service top-level configuration element. Provided with the
name
attribute.- Configuration variable
An RTI-specific construct to be used in XML to define content that can be expanded at runtime.
- Shipped executable
An RTI-provided command-line executable that runs an RTI Service.
- Library API
Public API that allows you to embed an RTI Service into your custom application.