17.1.1. RPC Service¶
A Service is the RPCEntity used to register all RPCEntities involved in an RPC communication, both on the client side (Requesters) and on the server side (Repliers). Two or more participants can communicate with each other via RPC if they register the same service and create Requesters and Repliers in it.
A service is represented by its name and a Service type,
so that two Service
instances represent the same RPC service if they have the same name and type.
The name of the Service and the name of its type can be obtained through the methods get_service_name()
and get_service_type_name()
respectively.
Similarly to the rest of the RPC entities, Service
instances can be enabled or disabled,
according to whether they contain DDS entities or not:
Each active Service contains at least two DDS entities: a Request Topic, which is used to publish and receive Request samples, and a Reply Topic, which is used to publish and receive Reply samples. If it also contains enabled Requesters and Repliers, it also includes their respective internal DataWriters and DataReaders. Therefore, an enabled
Service
instance can also be understood as the subset of DDS entities associated with a DomainParticipant that participate in the same communication through RPC.Each disabled Replier does not contain any DDS entity and is ignored by the middleware. Therefore, it cannot take requests nor send replies.
17.1.1.1. Service types¶
Due to the fact that a Service represents a Request/Reply communication,
a Service type is represented by a pair of topic types: the Request topic type and the Reply topic type.
A new Service type can be defined creating an instance of ServiceTypeSupport
class,
which is constructed using TypeSupport
instances of both Request and Reply types.
DomainParticipant
class have register_service_type()
and
unregister_service_type()
methods
to register and unregister a ServiceTypeSupport
instance, respectively.
Note
Request and Reply types associated with a service type named <service_type_name>
are registered
in the participant with the names <service_type_name>_Request`
and
<service_type_name>_Reply
, respectively.
A registered ServiceTypeSupport
can be found by name using find_service_type()
method;
if a Service type with the provided name is not found, an empty ServiceTypeSupport
is returned.
Note
Trying to register a different ServiceTypeSupport
instance with a
service_type_name
already registered will return a ReturnCode_t
error.
Registering and unregistering a ServiceTypeSupport
instance involves
registering and unregistering the Request and Reply types in the participant, respectively.
If a ServiceTypeSupport
contains a Request or Reply type with the same name
as a previously registered type but with a different TypeSupport
,
the register_service_type()
method will fail.
Similarly, attempting to unregister a ServiceTypeSupport
instance with a Request or Reply type
that is used by a DDS endpoint on a topic not created by the Service will fail.
To avoid these issues, it is recommended to make sure that the Request and Reply types
are reserved for RPC communication though a unique service and
not used by external DDS entities which are not part of the Service.
17.1.1.2. Creating and deleting a Service¶
A DomainParticipant can create and register a
Service
instance using DomainParticipant::create_service()
method.
Respectively, a Service
can be unregistered and deleted using DomainParticipant::delete_service()
method.
Each registered Service can be found by name using DomainParticipant::find_service()
method.
Note
Before creating a new Service,
user must register the ServiceTypeSupport
instance associated with the Service type.
If there is no Service type registered with the service_type_name
provided,
Service is not created and DomainParticipant::create_service()
method will return a null pointer.
When a new Service is created, it is enabled by default. It means that DomainParticipant creates the topics used for publishing and receiving Request and Reply samples.
Note
If the DomainParticipant is unable to enable the Service when it is created, it is considered an error.
The instance is destroyed, and DomainParticipant::create_service()
returns nullptr
.
Only the DomainParticipant that created the Service
instance can delete it.
Attempting to delete a Service
instance from a different DomainParticipant
will result in a ReturnCode_t
error.
17.1.1.3. Enabling and disabling a Service¶
Service
instances can be enabled or disabled using
enable()
and close()
methods, respectively.
When a disabled Service
instance is enabled, new Request and Reply topics are created in the DomainParticipant
using the registered Service type. It also creates the content filtered topic used for Reply samples.
Additionally, if it contains Requesters and Repliers, an attempt will be made to enable all possible entities.
Note
Request and Reply topics are created with names
<service_name>_Request
and <service_name>_Reply
, respectively.
The ContentFilteredTopic
instance is also created
from the Reply topic instance with name <service_name>_ReplyFiltered
.
Note
If some of the RPCEntities within the Service cannot be enabled, an error log is displayed.
However, enable()
ignores this failure and returns RETCODE_OK`
as long as
the topics have been created successfully.
Reciprocally, when an enabled Service is disabled, all the DDS entities that the Service contains are destroyed, making the Service not participate in the communication through RPC. It implies disabling all containing Requesters and Repliers and deleting the Request and Reply topics.
Note
If some of the RPCEntities within the Service cannot be disabled,
close()
returns an error code.
17.1.1.4. Example¶
The following code snippet shows how to create and delete a Service instance:
TypeSupport request_type_support = TypeSupport(new CustomDataType());
TypeSupport reply_type_support = TypeSupport(new CustomDataType());
DomainParticipant* participant =
DomainParticipantFactory::get_instance()->create_participant(0, PARTICIPANT_QOS_DEFAULT);
// Create a new ServiceTypeSupport instance
ServiceTypeSupport service_type_support(request_type_support, reply_type_support);
// Register the ServiceTypeSupport instance in a DomainParticipant
ReturnCode_t ret;
ret = participant->register_service_type(service_type_support, "ServiceType");
if (RETCODE_OK != ret)
{
// Error
return;
}
// Create a new Service instance
Service* service = participant->create_service("Service", "ServiceType");
if (!service)
{
// Error
return;
}
// ... Create Requesters and Repliers here
// Delete the created Service
ret = participant->delete_service(service);
if (RETCODE_OK != ret)
{
// Error
return;
}