2. Core Concepts¶
This section aims to provide a deeper understanding of the Routing Service architecture and give you the required insight to configure and use it effectively.
You will learn about:
- Application resource model: Gives you a full picture of all the elements that compose Routing Service, including details about their relationships with the pluggable components and their lifecycle.
- Builtin plugins: Describes the builtin pluggable components that are part of the Routing Service module.
2.1. Resource Model¶
In this section you will learn the details of the Routing Service application resource model (see Section 12.1). It describes all the different resource classes, their functions and responsibilities, and their relationships with other resources.
Figure 2.1 shows a high-level view of the main classes that comprise the application resource model.
There are two main logical planes, each addressing orthogonal sets of capabilities:
- Data Plane: Set of resources associated with data flow, both user data and meta-data. A resource in this plane is also known as an entity. The data provision and processing is performed using plugins (see Section 7 for an overview of the list of available plugins).
- Control Plane: Set of resources associated with service monitoring and administration. These are the resources in charge of providing monitoring information and run-time administration of the resources from the data plane.
An alternative representation of the resource module is shown in Figure 2.2.
The next sections describe each entity with detail. The documentation for each entity will provide:
- A Description of the role and responsibility of the entity within Routing Service.
- The relationship, if any, with plugin components. This part will give you an understanding of how Routing Service achieves custom behavior.
- A Description of the states an entity can go through.
The next sections describe Routing Service from a generic point of view, independently of the Adapter (or any other type of plugin) that is used. To read more about how DDS is integrated with Routing Service, please see the (Section 2.2.1). It’s recommended though that you still review the general model for a solid understanding of Routing Service.
2.1.1. Directory¶
Table 2.1 provides a resource directory with quick links to access different types of information for each resource or entity.
2.1.2. Service¶
The Service is the top-level resource. The Service is the entity that encapsulates all the resources needed for the operation of both the control and data planes. Typically, a Service refers to an execution of Routing Service.
In the control plane, the Service is composed of the Monitoring and Administration resources, which are optionally available sub-services. These components are described in Section 6 and Section 5, respectively.
In the data plane, the Service is composed of a collection of user plugins instances and a collection of DomainRoutes.
2.1.2.1. Plugin Interaction¶
The Service is responsible for loading and owning any of the plugins that you can provide through the Software Development Kit (see Section 7). Figure 2.3 shows the relationship between the Service and the plugin objects.
See Section 12.4 for more information about plugin management.
2.1.2.2. Service States¶
A Service can be in one of the states listed in Table 2.2.
State | Description | Trigger | Plugin callback |
---|---|---|---|
ENABLED |
A Service object has loaded the specified service configuration. Monitoring and Administration services are started if they are enabled in the configuration. |
|
N/A |
STARTED |
A Service object has created all the underlying resources,
including creating and starting all the contained DomainRoutes, as
specified in the configuration. Additionally, the service discovery thread (SDT) is also started. The SDT sets the context to read the data from the builtin input/output stream discovery StreamReaders Plugin configurations are validated but the libraries are loaded and instances created lazily when they are first needed. |
|
N/A |
STOPPED |
A Service object has deleted all the resources created during the start phase: the service discovery thread and DomainRoutes are deleted. Additionally, any plugin instances are deleted. |
|
|
DISABLED |
A Service object has deleted all the resources created during the enable phase. Entering this state occurs only temporarily while the Service object is being deleted. |
|
N/A |
2.1.3. DomainRoute¶
A DomainRoute defines a collection of independent data domains (such as DDS, MQTT, AMQP, etc.), each modeled as a Connection. It’s also composed of a collection of Sessions.
2.1.3.1. DataReader States¶
A DomainRoute can be in one of the states listed in Table 2.3.
State | Description | Trigger | Plugin callback |
---|---|---|---|
ENABLED |
A DomainRoute object has created all the underlying Connections and Sessions as indicated in the configuration. |
|
N/A |
STARTED |
A DomainRoute object has enabled all the contained Connections and started all the contained Sessions. The DomainRoute is attached to the service discovery thread and may start processing stream discovery data. |
|
N/A |
STOPPED |
A DomainRoute object has stopped all Sessions and disabled all the Connections. The DomainRoute is detached from the service discovery thread. |
|
N/A |
DISABLED |
A DomainRoute object has deleted all the underlying Connections. Entering this state occurs only temporarily while the DomainRoute object is being deleted. |
|
N/A |
2.1.4. Connection¶
A Connection defines an access point to a specific data domain. The access to a data domain is provided through an instance of an Adapter plugin, which is specified in the configuration (See Table 4.7 and Table 4.8). For example, the associated Adapter plugin implementation could provide a connection to an HTTP Server through an HTTP Client, or a logical connection to a DDS Domain through a DomainParticipant.
The Connection is also responsible for tracking all the stream information that is provided by the underlying input and output stream discovery StreamReaders. The Connection gets notified about new or disposed streams and propagates this information downstream to the Routes and AutoRoutes, which will process and generate events accordingly.
Note
A DomainParticipant is a special type of Connection that represents an instance of a
DdsConnection
. For this case, special custom tags are available that
facilitate configuring the DdsConnection
.
2.1.4.1. Plugin Interaction¶
Figure 2.4 shows the relationship with the plugin
objects. A Connection shall hold one, and only one, adapter::Connection
object.
2.1.4.2. Connection States¶
A Connection can be in one of the states listed in Table 2.4.
State | Description | Trigger | Plugin callback |
---|---|---|---|
ENABLED |
A Connection object has created the underlying Adapter connection object. |
|
|
DISABLED |
A Connection object has deleted the Adapter connection object it holds. |
|
AdapterPlugin::
delete_connection |
2.1.4.3. Type Registration¶
The Connection is the entity where type registration takes place. A Connection keeps a list of registered types, where each entry in the list contains:
- registered type name: Unique name used to identify and register a concrete type within the Connection.
- type representation: In-memory structure that describes the type itself.
The type representation is adapter-dependent and Routing Service assumes
TypeCode
as default type representation for types.
A type is associated with a stream and its registration is required in order to create StreamReaders and StreamWriters. A type can be registered in two ways:
- Through stream discovery information, provided by the builtin stream discovery StreamReaders. On stream discovery, the associated information contains the registered name and the representation for a type.
- Through XML Connection configuration (see Section 4.5.7.2.1).
A type definition is provided in XML and the Routing Service parser will generate a
TypeCode
from it. Connection configuration can then reference this XML type definition to register it.
2.1.5. Session¶
A Session defines a collection of Routes and AutoRoutes. It also defines a multi-threaded safe context for Route event processing.
Events from a Route are processed sequentially within the same Session. A Route event is processed by a single thread at a time. That is, the same route cannot be processed concurrently. However, within a Session, different Routes that can be processed concurrently, as many as the number of threads available within the Session.
Figure 2.5 shows the event processing mechanism.
Consider a Session with a pool of N
threads and composed of P
Routes.
- Session threads are idle waiting for Routes to become active. An active Route is one that has events pending processing.
- Once an active Route is selected for processing, all the pending events at that time will be consumed sequentially one after the other (see Section 2.1.6 for information about route processing). To prevent starvation, new events arriving will be deferred for the next selection cycle.
- A Session selects Routes for processing in a round-robin fashion, following
the same order as they are defined in the Session configuration. At a
maximum only
N
Routes can be processed concurrently. Remaining active Routes will wait until a thread becomes available.
Figure 2.5 shows a Session concurrently processing
N
active Routes. Other remaining P-N
Routes, such as RouteP,
are active and waiting for a thread to become available;
RouteP-1 is not active (no pending events).
2.1.5.1. Plugin Interaction¶
Figure 2.6 shows the relationship with the plugin
objects. A Session shall hold one adapter::Session
object for each
Connection in the parent DomainRoute.
2.1.5.2. Session States¶
A Session can be in one of the states listed in Table 2.5.
State | Description | Trigger | Plugin callback |
---|---|---|---|
ENABLED |
A Session object has created all the underlying adapter::Session
objects. It has also created all the AutoRoutes and Routes that are
defined in the configuration. |
|
Connection::create_session |
STARTED |
A Session object has started the thread pool, and enabled all the underlying AutoRoutes and Routes. In this state, the Session is actively processing Route events. |
|
N/A |
STOPPED |
A Session object has stopped the thread pool, and disabled all the underlying AutoRoutes and Routes. |
|
N/A |
DISABLED |
A Session object has deleted all the adapter::Session
objects it holds. |
|
Connection::delete_session |
2.1.6. Route¶
A Route defines a processing unit for data streams. A Route is composed
of N
Inputs and M
Outputs, each referencing any of the Connections
defined as part of the parent DomainRoute.
A Route generates certain events that are processed safely and serially within one of the threads from the parent Session. Route events are processed through a pluggable Processor.
Note
A TopicRoute is a special type of Route. All its Inputs and Outputs are tied to the builtin DDS Adapter. For this case, special and custom tags are available that facilitate configuring the TopicRoute.
2.1.6.1. Plugin Interaction¶
Figure 2.7 shows the relationship with the plugin objects. A Route shall hold one Processor object, which will receive the notifications of the events affecting the owner Route.
For more information about the Processor behavior and Route events, see the main page of API documentation (Section 7).
2.1.6.2. Route States¶
A Route state machine is shown in Figure 2.8.
Table 2.6 shows all the states a Route can enter.
State | Description | Trigger | Plugin callback |
---|---|---|---|
ENABLED |
A Route has created the underlying Processor. The Route is attached to the parent Session and is receiving event notifications. |
|
|
DISABLED |
A Route has deleted the underlying Processor. The Route is detached from the parent Session so no events are notified. |
|
ProcessorPlugin::
delete_processor |
STARTED |
A Route has enabled all its Inputs and Outputs. |
|
Processor::on_route_event |
STOPPED |
A Route has disable at least one of its Inputs and Outputs. |
|
Processor::on_route_event |
RUNNING |
A Route is ready to process data stream related events. These include:
|
|
|
PAUSED |
A Route is temporarily suspending the processing of data stream related events. |
|
Processor::
on_route_event |
2.1.7. AutoRoute¶
An AutoRoute represents a factory of single-input single-output Routes. An AutoRoute creates Routes based on a name filter criteria that matches the name or type of a stream.
An AutoRoute creates a Route for each pair:
where Sm and Tn are the name for the stream m
and
the name of the type n
, respectively. The generation of a Route
occurs only on the event of a newly discovered stream. The resulting Route
has a single Input and a single Output, both for the same stream name and
type.
The created Route executes within the context of the parent Session of the AutoRoute. Figure 2.9 illustrates this relationship.
The AutoRoute creates a Route only if it has not previously matched the Sm and Tn pair. AutoRoutes never delete the created Route, independently of whether the matching streams are disposed or not.
Note
An AutoTopicRoute is a special type of AutoRoute whose Inputs and Outputs are tied to the builtin DDS Adapter. For this case, special and custom tags are available that facilitate configuring the AutoTopicRoute.
2.1.7.1. AutoRoute States¶
An AutoRoute can be in one of the states listed in Table 2.7.
State | Description | Trigger | Plugin callback |
---|---|---|---|
ENABLED |
AutoRoute object is read to start matching streams and create Routes. Previously discovered streams are matched retroactively. |
|
N/A |
STARTED |
This state is equivalent to the ENABLED state and the transition
is automatic upon enabling. This state is added for consistency with
the other entities. |
|
N/A |
STOPPED |
This state is equivalent to the DISABLED state and the transition
is automatic upon disabling. This state is added for consistency with
the other entities. |
|
N/A |
DISABLED |
AutoRoute stops matching all newly discovered streams. All the Routes created from this AutoRoute are deleted. |
|
N/A |
2.1.8. Input¶
An Input is responsible for obtaining data associated with a specific stream uniquely identified by its name and type. An Input must reference an existing Connection within the parent DomainRoute. The referenced Connection determines the data domain where the Input will obtain data.
An Input has scope only within the parent Route. It cannot be shared in other Routes. If another Route requires accessing the same data stream, a new Input shall be defined within such Route.
2.1.8.1. Plugin Interaction¶
Figure 2.10 shows the relationship with the plugin
objects. An Input shall hold one, and only one, adapter::StreamReader
object.
2.1.8.2. Input States¶
An Input can be in one of the states listed in Table 2.8.
State | Description | Trigger | Plugin callback |
---|---|---|---|
ENABLED |
Input has created its underlying StreamReader and it’s ready to read data. | The following two conditions shall be met:
|
|
STARTED |
This state is equivalent to the ENABLED state and the transition
is automatic upon enabling. This state is added for consistency with
the other entities. |
|
N/A |
STOPPED |
This state is equivalent to the DISABLED state and the transition
is automatic upon disabling. This state is added for consistency with
the other entities. |
|
N/A |
DISABLED |
Input has deleted its underlying StreamReader and can no longer read data. | Creation mode condition becomes false |
|
2.1.9. Output¶
An Output is responsible for writing data associated with a specific stream uniquely identified by its name and type. An Output must reference an existing Connection within the parent DomainRoute. The referenced Connection determines the data domain where the Output will provide data.
An Output has scope only within the parent Route. It cannot be shared in other Routes. If another Route requires access to the same data stream, a new Output shall be defined within such Route.
2.1.9.1. Plugin Interaction¶
Figure 2.11 shows the relationship with the plugin
objects. An Output shall hold one, and only one, adapter::StreamWriter
object. Optionally, an Output can hold one, and only one,
transformation::Transformation
object.
The Output provides the data to a domain by calling the StreamWriter::write
operation. If a Transformation is present, the Transformation::transform
operation is called right before writing on the StreamWriter, followed by a
Transformation::return_loan
right after.
2.1.9.2. Output States¶
An Output can be in one of the states listed in Table 2.9.
State | Description | Trigger | Plugin callback |
---|---|---|---|
ENABLED |
Output has created its underlying StreamWriter and it’s ready to write data. | The following two conditions shall be met:
|
|
STARTED |
This state is equivalent to the ENABLED state and the transition
is automatic upon enabling. This state is added for consistency with
the other entities. |
|
N/A |
STOPPED |
This state is equivalent to the DISABLED state and the transition
is automatic upon disabling. This state is added for consistency with
the other entities. |
|
N/A |
DISABLED |
Output has deleted its underlying StreamWriter and can no longer write data. | Creation mode condition becomes false |
|
2.2. Builtin plugins¶
Builtin plugins come pre-registered in memory within Routing Service. Any configurable aspects are available through dedicated special tags for enhanced usability.
2.2.1. DDS Adapter¶
This is an Adapter implementation that provides access to DDS domains. Figure 2.12 shows the architecture of the DDS Adapter.
Most of the use cases expect to have DDS as the main data domain in the user data plane. For this reason, you will find that Routing Service specializes some entities so that they are directly associated with DDS. These entities are:
- Participant
- AutoTopicRoute
- TopicRoute
- DdsInput
- DdsOutput
These entities are equivalent to the generic entities shown in Figure 2.1 except that the Adapter entity they enclose is created from the builtin DDS Adapter (Section 2.2.1). Figure 2.13 shows the DDS specialization of the generic resource model.
2.2.1.1. DDS AdapterPlugin¶
The DdsAdapter
is an implementation of the Adapter interface. It’s
responsible for creating DDS Connections.
Mapping | Configuration Tag |
---|---|
It uses the DomainParticipantFactory to create the participants needed by each DDS Connection | <participant_factory_qos> (only in USER_QOS_PROFILES.xml ) |
2.2.1.2. DDS Connection¶
The DdsConnection
is an implementation of the Connections interface.
It is responsible for joining to a specific DDS Domain. It’s also the factory
for creating DDS Sessions, StreamReaders and StreamWriters.
The DdsConnection
relies on the DdsAdapter
for creating DomainParticipants. This
class creates the Topics associated with the DataReaders and DataWriters it also
creates.
Mapping | Configuration Tag |
---|---|
Composed of only one DomainParticipant | <domain_route>/<participant> (see Table 4.8) |
2.2.1.3. DDS Session¶
The DdsSession
is an implementation of the Session interface. It’s
responsible for creating Subscribers and Publishers.
Mapping | Configuration Tag |
---|---|
Composed of only one Publisher and one Subscriber | <session>/<subscriber_qos> and <session>/<publisher_qos>
(see Table 4.9) |
Note that, as explained in Section 2.1.5.1,
a new DdsSession
object is instantiated for each pair <session>
and
<participant>
element within the parent DomainRoute.
2.2.1.4. DDS StreamReader¶
The DdsStreamReader
is an implementation of the StreamReader interface. It’s
responsible for reading data from a Topic and providing it to the parent
Route, which is in charge of processing it through the installed Processor.
Mapping | Configuration Tag |
---|---|
Composed of only one DataReader | <route>/<dds_input> and <topic_route>/<input>
(see Table 4.13) |
The referenced DDS Connection and parent <session>
determines from which
DomainParticipant and Subscriber the DataReader is created.
The configuration of the Input owning the StreamReader indicates:
- The referenced DDS Connection that contains the DomainParticipant
- The parent
<session>
, which along with the referenced Connection, determines whichDdsSession
and hence Subscriber is used to create the DataReader. - The name of the Topic in the domain of the DomainParticipant.
2.2.1.5. DDS StreamWriter¶
The DdsStreamWriter
is an implementation of the StreamWriter interface. It’s
responsible for writing data to a Topic. The data is provided by the parent
Route through the installed Processor.
Mapping | Configuration Tag |
---|---|
Composed of only one DataWriter | <route>/<dds_output> and <topic_route>/<output>
(see Table 4.13) |
The referenced DDS Connection and parent <session>
determines from which
DomainParticipant and Publisher the DataWriter is created.
The configuration of the Output owning the StreamWriter indicates:
- The referenced DDS Connection that contains the DomainParticipant
- The parent
<session>
, which along with the referenced Connection determines whichDdsSession
and hence Publisher is used to create the DataWriter. - The name of the Topic in the domain of the DomainParticipant.
2.2.2. Forwarding Processor¶
This is a Processor implementation that forwards samples within a Route.
The plugin registered name is reserved and has the value
rti.routingservice.RoutingProcessor
.
The functions of the builtin forwarding Processor are:
- Forwarding all the live data samples received from each Input to each Output.
- Proxying the TopicQueries received by the
DdsStreamWriter
, making sure all the TopicQuery data samples received from each Input are sent to the corresponding Outputs and final destination DataReaders. (see Section 9.2).
The builtin forwarding Processor is set by default in all AutoRoutes and Routes.
Note that if you install your own Processor implementation, you will override
the functionality described above. In this case, even if the dedicated
configuration tags are specified (such as <topic_query_proxy>
), they will
not have any effect.