Connexis Services

The Connexis model library consists of a set of capsules, protocols, classes and data types. Together they implement a number of services which your UML-RT application can utilize in order to implement communication across process boundaries. That is, to realize a distributed application.

If you followed the Tutorial: Building a Distributed Application with Connexis you have already some experience of using a few of the services that are provided by Connexis. In this chapter, we will go through all services provided by the Connexis library, and describe how you can use them in your model, and, where possible, how you can customize their behavior.

From a practical point of view, the use of a Connexis service typically means to add a few elements to your model (e.g., a capsule part or a port). Often several elements need to be added and configured properly. To make this easier you can take advantage of the Connexis profile. It abstracts the implementation details of the Connexis library into high-level settings, realized as stereotype properties. Rather than manually adding the necessary elements from the Connexis library to your model, you can apply stereotypes from the Connexis profile and set values for the properties of those stereotypes. The profile will then automatically update your model as necessary. The profile can both add necessary elements (when a new service should be used) or remove them (when an existing service no longer is needed). This speeds up the process of building a model with Connexis. However, if you prefer you can of course manually do the same things as the profile does.

The Connexis library elements that constitute the interface you should use in your application, are located in the RTDInterface package. If you use the Connexis profile this package is automatically imported in your model.

Otherwise you can find this package in the DCS model library at this location: DCS::Logical View::DCSModelInterfaces::RTDInterface.



Base Service

The Base service is a core service that each component that will use Connexis in your application must use. It is implemented by means of the RTDBase capsule of the Connexis library. This service is also the entry point for accessing most other Connexis services.

To use this service first select an appropriate capsule in each component of your application. Often it's a natural choice to select the top capsule of each component. Then apply the "Connexis Feature" stereotype on the selected capsules. Each selected capsule will then get a capsule part typed by the RTDBase capsule.

The "Connexis Feature" stereotype provides the following stereotype properties:

Feature Description
CDM Transport Specifies whether CDM transport should be used in this Connexis component. See Transport Registration for more information.
CRM Transport Specifies whether CRM transport should be used in this Connexis component. See Transport Registration for more information.
Locator Functionality Specifies whether this Connexis component should contain a Locator. See Locator Service.
RTD InitStatus Port Specifies whether this Connexis component will be notified about the initialization status of the Connexis library. See Initialization Status Service.
RTD Metrics Port Specifies whether this Connexis component should use the Metrics Service.
Target Agent Functionality Specifies whether this Connexis component should be instrumented to allow debugging of the distributed application. Note that debugging is done by means of the Connexis Viewer, which currently is not available in Model RealTime. It is available in Rational Rose RealTime. Also note that if you set this property to True, "CDM Transport" will also be set to True automatically since the Connexis Viewer uses the CDM transport.

Depending on how you choose the values for these stereotype properties, the type of the base capsule part will be set differently. It may either be RTDBase, or a capsule that inherits from RTDBase. The different configurations are summarized in the table below:

Configuration Capsule Description
Minimal RTDBase This is the minimal configuration where the component will not contain the Locator, nor the Target Agent for debugging with the Connexis Viewer. This configuration gives the smallest overhead in terms of the size of the executable.
Target Agent RTDBase_Agent This configuration includes the Target Agent but the Locator is not linked in with the executable.
Locator RTDBase_Locator This configuration includes the Locator but the Target Agent is not included.
Target Agent and Locator RTDBase_Locator_Agent This configuration includes both the Locator and the Target Agent. The configuration leads to the biggest overhead in terms of the size of the executable since both the Locator and the Target Agent are linked into the executable.

Transport Registration

A transport must register with Connexis prior to the initialization of the library. The default way of performing this registration is to do it when the Connexis Feature capsule is incarnated (which happens when the component starts up in case it is the top capsule). If you have configured your Connexis Feature capsule to use either CDM or CRM transport, the capsule will have an attribute typed by either RTDCdm or RTDCrm. The constructor of these classes perform the registration of the transports.

The default constructor will register the transport so that it listens for messages on the transporter's thread. This gives the best performance. However, only one transport can do this, so if your component uses multiple transports, the first one that is registered with Connexis will get this behavior. In order to be more explicit about which transport that should get this behavior, and not rely on the order in which the transport attributes are initialized, you can use instead the constructor that takes a boolean parameter. If you pass "false" to the constructor, the transport will instead use a separate thread for listening for messages.

If your component uses a custom transport, the initialization may be done in a different way, for example using a constructor with different parameters. However, any transport must be registered with Connexis before the library is initialized, so it is in general a good idea to do it when the Connexis Feature capsule is incarnated.

Initialization Status Service

Before an application can use any Connexis feature, the Connexis library must have been initialized. The Initialization Status Service is the recommended approach for how the application can get notified when this initialization is completed.

When you set the stereotype property "RTD InitStatus Port" to "True" the Connexis Feature capsule will get a port "RTDInitStatus" typed by the RTDInitStatus protocol. This is an SAP port that is automatically registered with the registration string ":RTDInitStatus". The Connexis library contains a corresponding SPP port, and when the Connexis library has been fully initialized, these ports will be connected. This means that when the rtBound event arrives on the "RTDInitStatus" port, the Connexis initialization is completed, and the application can then start to use Connexis features.

If there are more capsules in the application that need to be notified when Connexis has been initialized, they can follow the same approach. Create a port in the capsule typed by the RTDInitStatus protocol and make sure the Notification property is turned on. If you prefer to register the port manually, set the Registration Kind property to "Application" and then register the port like this:

rTDInitStatus.registerSAP(":RTDInitStatus");

By default at most 50 clients can subscribe and get notified through this port. This limit is controlled by the constant DCS::Logical View::DCSComponents::DCSSysConfig::RTDConstants::rtdMaxStatus.

The RTDInitStatus protocol provides a number of Out Events and In Events that can be sent or received as soon as Connexis has been initialized. The table below describes these events:

Event Direction Description
rtdAgentActive Out Request for Target Agent activation status.
rtdAgentActiveReply (data : int) In Reply for the above event. The data tells whether the Target Agent is active (1) or not (0).
rtdBackupEndpoint (data : RTString) Out Set the endpoint of the backup locator. The data is the endpoint string, in the same format as the CNXlbep command line option. Examples:
cdm://localhost:4000
tcp://192.139.251.2:5000
rtdBackupEndpointReply (data : int) In Reply for the above event. The data tells whether the request to set the backup locator endpoint was successful or not:
0 - success
1 - failed because this process is the backup locator
2 - failed due to an invalid endpoint string
rtdCDMport Out Request for the value of the CDM port assigned.
rtdCDMportReply (data : int) In Reply for the above event. The data is the CDM port, which was either specified by means of the CNXep command line argument, or automatically assigned to a free port number. A zero value indicates a software failure.
rtdDCSrunning Out Request for the initialization status of Connexis. There is usually no need to send this event, since when rtBound has been received, it's already known that Connexis has been initialized and is running.
rtdDCSrunningReply (data : int) In Reply to the above event. The data tells whether Connexis is initialized and is running (1) or not (0).
rtdLocatorAvailable Out Request for Locator availability status. If the Locator is present in the component and properly configured it will be considered as available.
rtdLocatorAvailableReply (data : int) In Reply to the above event. The data tells whether a Locator is available or not.
A zero value implies that the locator is NOT properly configured and the registration of global names will fail:
port-name.registerSAP("dcs:/service-name") // will fail
port-name.registerSPP("dcs:/service-name") // will pass since SPPs can also be connected locally and explicitly.
A non-zero value indicates that the Locator is available though a connection may not exist at this time to a remote Locator. Registration of global names will pass.
In this case the value gives additional information about the status of the Locator:
1 - Primary Locator running locally (this process), Backup Locator not configured
2 - Primary Locator running locally (this process), Backup Locator is remote (CNXlbep)
3 - Backup Locator running locally (this process), Primary Locator is remote (CNXlpep)
4 - Primary Locator is remote (CNXlpep), Backup locator not configured
5 - Primary Locator is remote (CNXlpep), Backup locator is remote (CNXlbep)
rtdPrimaryEndpoint Out Set the endpoint of the primary locator. The data is the endpoint string, in the same format as the CNXlpep command line option.
rtdPrimaryEndpointReply In Reply for the above event. The data tells whether the request to set the primary locator endpoint was successful or not:
0 - success
1 - failed because this process is the primary locator
2 - failed due to an invalid endpoint string
rtdTransportController Out Request for the Transport thread (i.e. a pointer to its Controller). High-performance Connexis applications where capsules are collocated on the same thread as the Transport can perform this request and incarnate the capsules on the returned Controller.
rtdTransportControllerReply (data : long long) In Reply to the above event. The data is the address of the Controller for the Transport. Cast it to an RTController pointer:<br>RTController * t_thread = (RTController *)*rtdata;
A null pointer is returned if Connexis has not been initialized.
rtdVClimit Out Request for the limit on the maximum number of Virtual Circuits (VCs). This limit is defined by the constant DCS::Logical View::DCSComponents::DCSSysConfig::RTDConstants::rtdMaxStatus.
rtdVClimitReply (data : int) In Reply to the above event. The data is the maximum number of Virtual Circuits that Connexis is configured to handle.

For the special case when the Connexis Feature capsule runs on the main thread in a fixed capsule part, it's not strictly necessary to use the Initialization Status Service, because in that case you can know that Connexis has already been initialized when the capsule state machine starts to run. However, it's still recommended to use the Initialization Status Service so that your application will continue to work even if you later decide to run the Connexis Feature capsule on another thread.

Locator Service

The Locator Service allows a distributed application to communicate without using explicit endpoint addresses (such as IP addresses and ports). The Locator is a name server and introduces an indirection where the application instead uses logical service names to refer to the endpoints that are connected.

The Locator Service supports both a primary and a backup locator. In this way, a distributed application can be made more robust by ensuring that the name server is not a single point of failure. The backup locator automatically takes over if the primary locator for some reason become unavailable (for example because its container executable has crashed or is non-responsive).

Depending on the nature of your application you may or may not benefit from the Locator Service. Here are some examples when it makes sense to use it:

To use the Locator Service simply set the stereotype property "Locator Functionality" to "True". The RTDBase capsule part of the Connexis Feature capsule will then be retyped to RTDBase_Locator. If you also have set the "Target Agent Functionality" to "True" the type will instead be RTDBase_Locator_Agent. You have to perform this step in each component that should contain a Locator (either a primary or backup locator).

The use of the Locator Service has a very small impact on the application. The only difference is in the registration strings that are used when registering ports. They are on the following form:

dcs:/<service-name>

The service name can be any string that describes the service which the registered SPP port provides to connected SAP ports.

Publisher Ranking

Multiple SPP ports can use the same service name. In this case the Locator Service performs a ranking of all those ports. The port with the highest rank will be used for the binding when an SAP port is registered with the same service name. The rank of a publisher is specified in the registration string by means of a registration parameter. Here is an example:

dcs:/theService((locator_rank, 1))

The default rank of a publisher is zero.

Ranking makes it possible to dynamically replace a certain publisher with another one. Subscribers that are already bound to a publisher remain bound to it, but new subscribers will be bound to the other publisher since it has a higher rank.

If there are multiple registered publishers with the same rank the Locator Service will prioritize one that has a certain transport protocol, if a preferred transport has been specified. Such a preferred transport can be done using a registration parameter in the registration string. For example:

dcs:/theService((locator_transport, crm))

If there is no such preferred transport for the individual subscriber, the Locator Service will next check if the command-line option CNXlocatorpreferredtransport has been used to specified a preferred transport.

As a last resort, if there still are multiple matching publishers a round-robin scheme is used to decide to which of those publishers the subscriber will be bound. In this case the binding of a subscriber to a publisher hence becomes non-deterministic.

Locator Dynamics

From the perspective of the user application, the Locator Service is simple to use without knowing anything of how it works internally. However, for an increased understanding of the locator dynamics, let's look at what really happens when an SAP port gets bound to an SPP port by means of the Locator Service:

As can be seen in the diagram above, several internal messages are exchanged between the Connexis applications and the Locator to realize the binding. You should be aware of this overhead when designing your application. However, once the SAP port is bound to the SPP port there is no overhead introduced by the Locator Service. In fact, the Locator Service is not at all involved in the actual communication between the two applications which takes place after the ports have become connected.

Another thing to be aware of is what happens when a publisher becomes fully subscribed, i.e., when all the ports of the publisher (as determined by the port multiplicity) have been subscribed to. When this happens, there is not room for another subscriber to be bound to the publisher. The publisher therefore "unpublishes" itself from the Locator. Thereby a future subscriber can be bound to another publisher that is registered with the same service name, possibly with a lower rank. If one of the subscribers are deregistered from a fully subscribed publisher, the publisher once again publishes itself with the Locator. The diagram below illustrates what happens:

Backup Locator

If the distributed application uses a backup locator it should be placed in a different executable than the primary locator. It can then take over the job of the primary locator if it becomes unavailable (for example because its application crashes). You hence avoid a single point of failure in the application.

The backup locator continously polls the primary locator, and if it doesn't get a timely response it will assume the primary locator is unavailable and start the fail-over procedure. The backup locator broadcasts a message to all endpoints to inform that it now is the new primary locator. Each endpoint acknowledges this message by republishing all Connexis publisher ports, as well as all Connexis subscriber ports that are pending to be connected. This procedure takes some time, and in the meanwhile new registrations of SPPs or SAPs with locator registration strings will be delayed (but not lost) until the backup locator is ready to take over.

If the primary locator later becomes available again it will automatically take the role as the new backup locator. It is therefore usually enough with one level of locator backup.

The picture below illustrates the fail-over procedure when the backup locator takes over the responsibility of the primary locator:

Locator Race Condition

In the time that passes between the locator resolves the endpoint of a publisher and when a subscriber gets bound to that publisher it can happen that the publisher becomes unavailable, for example because it is deregistered. Such a scenario is illustrated below:

Here the locator does not get notified about the binding of subscriber2 until after subscriber1 is registered. Hence subscriber1 will attempt to bind to the publisher, but this will fail assuming that the publisher is an SPP port with multiplicity 1. In this case subscriber1 will simply subscribe again with the locator. The subscription will become pending until either a matching publisher becomes available, or the SAP port is deregistered so that it gets unsubscribed from the locator.

Locator Configuration

Command-line options are used for specifying the locator configuration. This includes information about which locator that should be the primary, and which that should be the backup. There are also a few other command-line options that can be used for specifying how the locator(s) should operate.

Read more about the available command-line options in Connexis Command Line Options.

The table below lists common locator configurations and the corresponding command-line options used:

Configuration Command-line Options Comment
When starting an executable that hosts the primary locator and no backup is being used. CNXlp The CNXlp option ("lp" = locator primary) establishes the process as the primary locator.
When starting an executable that hosts the primary locator and a backup is being used. CNXlp, CNXlbep The CNXlbep option ("lbep" = locator backup endpoint) informs about the existence and location of the backup locator.
When starting an executable that hosts the backup locator. CNXlb, CNXlpep The CNXlb option ("lb" = locator backup) establishes the process as the backup locator.
The CNXlpep option ("lpep" = locator primary endpoint) informs about the existence and location of the primary locator.
When starting an executable that is using a primary locator with no backup. CNXlpep
When starting an executable that is using a primary locator with a backup. CNXlpep, CNXlbep

Below are some examples of starting executables that are part of a distributed application that uses the Locator Service:

Example 1: Two node application with no backup locator

To start the executable that acts as the primary locator:

<app1_name> -CNXep=cdm://host1:9999 –CNXlp

To start the other executable:

<app2_name> -CNXep=cdm://host2:9991 -CNXlpep=cdm://host1:9999

Example 2: Three node application with primary and backup locator

To start the executable that acts as the primary locator:

<app1_name> -CNXep=cdm://host1:9999 -CNXlp -CNXlbep=cdm://host2:9999

To start the executable that acts as the backup locator:

<app2_name> -CNXep=cdm://host2:9999 -CNXlb -CNXlpep=cdm://host1:9999

To start the third executable:

<app3_name> -CNXep=cdm://host3:9991 -CNXlpep=cdm://host1:9999

-CNXlbep=cdm://host2:9999

Customizing the Locator Service

The Locator Service is implemented in a general fashion to make it usable in many kinds of distributed applications. As already described the Locator Service has several features that make it more than a simple name service:

If you only want to do minor modifications to the behavior of the Locator Service you can simply copy the DCS model library and modify it according to your needs (see Customizing and Porting the Connexis Library). However, sometimes not all of the above features may be needed by a certain distributed application, and in that case you may choose to implement another mechanism for resolving service names to physical endpoint addresses.

One example could be to use service names that follow a certain pattern, so that the endpoint address can be derived directly from the service name. Another example could be to use a configuration file that all involved executables read at start-up. Thereby it becomes possible to do the name lookup locally in each executable which can give good performance.

Metrics Service

The Metrics Service can provide various metrics collected in a distributed application. Such metrics can help you identify performance bottlenecks and in general monitor the health of the application.

To use the Metrics Service, you need to add a metrics port to a capsule and subscribe it to the Metrics Service. If you use the Connexis profile, you can just set the stereotype attribute "RTD Metrics Port" to "True" in your "Connexis Feature" capsule. This will create the metrics port which is called "RTDMetrics" and is typed by the protocol RTDMetrics.

To subscribe the port to the Metrics Service register it with the following registration string:

dcs:RTDMetrics

This will connect the port to the Metrics Service of the local executable. However, you can also connect it to a Metrics Service of a remote executable in order to collect metrics from that executable. In that case use this registration string:

dcs://<host>:<port>/RTDMetrics

By default at most 50 clients can subscribe and get notified from each instance of the Metrics Service. This limit is controlled by the constant DCS::Logical View::DCSComponents::DCSSysConfig::RTDConstants::rtdMaxStatus.

You can register the metrics port as soon as the application has started up, but you must wait for it to receive the rtBound event before you start to request any metrics.

The RTDMetrics protocol provides a number of Out Events and In Events that can be sent or received to collect metrics, turn on or turn off metrics collection, or clear collected metrics data. The table below describes these events:

Event Direction Description
rtdMetricsCollectOn Out Turn on metrics collection in the application that hosts the Metrics Service.
rtdMetricsCollectOnConfirm
rtdMetricsCollectOnFail
In Reply for the above event to indicate whether metrics collection was successfully turned on or not.
rtdMetricsCollectOff Out Turn off metrics collection in the application that hosts the Metrics Service.
rtdMetricsCollectOffConfirm
rtdMetricsCollectOffFail
In Reply for the above event to indicate whether metrics collection was successfully turned off or not.
rtdMetricsClear Out Clear all data collected by the Metrics Service.
rtdMetricsClearConfirm
rtdMetricsClearFail
In Reply for the above event to indicate whether collected metrics data was successfully cleared or not.
In
rtdMetricsInterval<br>(data : :int) Out Set the time interval for metrics collection. The data parameter specifies the number of seconds to wait between each metrics collection.
rtdMetricsIntervalConfirm<br>(data : :int) In Reply to the above event to indicate whether the metrics interval was successfully set or not. If the desired interval could not be set because it was too small, the minimal acceptable interval is set as the data. Otherwise the event data is the same as the interval that was requested.
rtdMetricsIntervalFail<br>(data : :int) In
rtdMetricsGet Out Request for metrics that have been collected up to this point in time.
rtdMetricsGetConfirm<br>(data : : RTDStats)
rtdMetricsGetFail
In Reply to the above event. In case of a successful request of metrics the rtdMetricsGetConfirm event will carry a data parameter typed by: RTDStats. Refer to this class in the Connexis library for information about what metric data is then returned (DCS::LogicalView::DCSModelInterfaces::RTDInterface::RTDStats).

In the prebuilt Connexis libraries that are shipped with Model RealTime the Metrics Service is by default enabled, but initially not turned on. If you want to turn on the collection of metrics before the metrics port has become bound you can use the special command-line option -CNXm=1. See Connexis Command-Line Options for more information.

If you never plan to use the Metrics Service, and want to optimize the size of the built executables, you can rebuild the Connexis library with the compile flag RTD_STATISTICS set to 0. See Customizing and Porting the Connexis Library.

Error Handling

Since Connexis binds registered ports asynchronously, error handling also is asynchronous. To get notified about errors related to a particular Connexis port, define a special In Event called "rtdError" in the protocol that types the port. This event should have a data parameter of type RTDErrorType. Each error that can occur is represented by one of the literals in the RTDErrorType enumeration:

Output Description
rtdDCSUninitialized = 1 Registration failed because Connexis was not initialized.
rtdZeroReplication = 2 Registration failed because the multiplicity of the port is zero.
rtdInvalidSyntax = 3 Registration failed because the registration string had an invalid syntax. See Registration String Grammar for the expected syntax.
rtdInvalidTransport = 4 Registration failed because the specified transport is not supported by this component.
rtdCircuitUnavailable = 5 Registration failed because no virtual circuit is currently available for the remote binding.
rtdLocatorUnavailable = 6 Global registration failed because no locator is available.
rtdConnectTimeout = 7 Explicit registration failed because a connection could not be established with the remote endpoint in a timely manner.
rtdEndpointUnavailable = 8 A connection cannot be made at present with the remote endpoint because it is currently unavailable.
rtdEndpointInaccessible = 9 A connection can never be made with the remote endpoint.

If an error occurs the "rtdError" event will be sent to the port at General priority. The exception is the last two errors which can occur even if the registration and binding was successful, and they are therefore sent at Background priority.

One common error in a distributed application is that a subscriber that has successfully connected to a publisher later will loose that connection. The reason can for example be that the publisher is deregistered, or that the application where the publisher resides terminates. Depending on the transport that is used such a broken connection may or may not lead to an error message. If the transport that is used does not provide this "quality of service", you have to use another mechanism to detect such problems. A common solution is to let the subscriber send a certain "are-you-alive?" event periodically to the publisher. The publisher should respond to this event within a certain time limit. If the subscriber does not get the response within that time limit, it will assume that the publisher is no longer available and can then deregister itself. It may then choose to wait for some time and try again, or it can register itself with another service name, representing a backup service to be used.