C++ API Concepts

This chapter provides an overview of the RTR C++ foundation classes and describes concepts that apply to application development using the this application programming interface (API). It includes conceptual descriptions of client and server interaction and application processing. Detailed information is provided on each class and its associated methods in later chapters of this manual. For code examples and implementation information, see the Design and Implementation chapter of this manual.

Overview

The C++ foundation classes enable you to implement new RTR client and server applications, or to integrate specific classes into existing applications to add additional functionality.

RTR concepts have been mapped to and implemented by the set of foundation classes for handling system management and the needs of business applications.

 

 

 

 

Figure 1-1 shows the C++ foundation classes. Management classes represent RTR, facilities, partitions, and key segments (part of the partitioning classes in Figure 1-1) whereas application classes represent transactions, data, messages and events.

The primary application classes include client classes, server classes, and data classes that are common to both client and server classes. There are also server and client transaction property classes.

You use management classes to implement applications that can help manage RTR. You use application classes to implement client and server applications. However, client and server applications can also use the management classes to dynamically set up RTR facilities and partitions.

Figure 1-1: C++ Foundation Classes

Facility, partition, and transaction property classes include methods that provide access to facilities, partitions, and transactions. These classes enable a program to obtain additional information on a facility, partition, or a transaction. Transaction property classes are useful for transaction recovery and for obtaining and setting transaction states.

Property classes work with other foundation classes in new applications; they can also be used independently in legacy RTR applications. They do this by using information that existing RTR applications already have, including transaction IDs (tids), facility names, and partition names.

 

Application Classes

RTR C++ foundation application classes include:

Data classes are common classes for passing data between client and server applications.

(Client and server transaction property classes are included within the client application classes and server application classes, respectively.)

To use RTR application classes, it is useful to understand RTR concepts necessary for implementing application solutions with the C++ API, C++ API-specific information, and object-oriented concepts.

Figure 1-2 illustrates the client and server classes and the paths through which they typically communicate. (There are design alternatives to the illustrated path.) TransactionController objects control transactions. Communication between client and server applications is through messages and events sent and received by the RTR application. Data objects (instances of data classes) carry these messages and events between RTR clients and servers.

Figure 1-2: C++ API Classes

The principal application classes are the transaction controller classes and data classes. A transaction controller object manages a transaction. The RTRData-derived data object is the common means through which client and server applications interact. A message handler encapsulates the data. Most events are not related to transactions. A message is sent from a client to a server or a server to a client (1-to-1). An event can go from one client or server to many clients and servers.

Transaction Classes

In RTR, a transaction is a logical grouping of messages.

A transaction is controlled by a TransactionController object. The client transaction controller class (RTRClientTransactionController) creates single instances of a transaction. The server transaction controller class (RTRServerTransactionController) manages single instances of a transaction.

A transaction controller object:

Typically, a transaction controller object processes multiple consecutive transactions, but there is at most one active transaction in a transaction controller object at any one time.

A transaction controller:

Data Classes

Applications use data objects to carry data between RTR clients and servers. Thus, the data classes are common to both client and server applications. RTRData is the base class from which four kinds of data are derived:

The class factory, RTRClassFactory, creates instances of data classes based on the content of a transaction controller Receive call for a message or event.

Communication between client and server applications is through messages and events. Data objects contain these messages and events sent and received by RTR clients and servers.

Figure 1-3 illustrates the data classes and their relationships to the RTRData base class and a memory buffer. For example, the base class of RTRStream is RTRData and the base class of RTRApplicationMessage is RTRStream.

Figure 1-3: Data Classes

An application wanting to send or receive data, specifies an RTRData object. The mechanism for sending and receiving is different as follows:

When calling SendApplicationMessage on a transaction controller, the caller specifies an RTRApplicationMessage.

When calling the Receive method, the application supplies an RTRData pointer to NULL. When the transaction controller determines the type of data which is about to be obtained it calls a class factory to create an instance of the appropriate object.

After a successful call to the Receive method, the RTRData pointer contains one of the following kinds of objects:

The RTRClassFactory class creates the above data objects. Based on the type of message contained on the transaction controller Receive call the class factory creates an instance of the appropriate data class. The class factory also enables you to customize the behavior of data object creation. An application may derive its own RTRClassFactory class and register it with the transaction controller. In this case, the transaction controller calls the application's class factory to create the data object.

Dispatch Methods and Handlers

Since all Data classes are derived from RTRData, an application can treat the data polymorphically, especially when receiving data on the server.

For example:

ServerTransactionController ServerTransactionController;

RTRData *pDataBeingReceived = NULL;

while (true)

{

// Receive some data

ServerTransactionController.Receive(&pDataBeingReceived);

// No need to determine what we received.
// Just call Dispatch()

pDataBeingReceived->Dispatch();

}

The RTRData class has a pure virtual method named Dispatch(). This means that all classes derived from RTRData provide an implementation of Dispatch(). This implementation of Dispatch, which is provided by the derived class, determines the exact message or event number that it contains and calls the appropriate method in the handler.

The message and event handler classes are:

An application may derive its own class from any or all of these handlers to provide its own custom handling of the specific messages and events.

Messages

Data objects carry messages between clients and servers. These messages are of two types:

Events

Data objects carry events between clients and servers. These events are of two types:

Application events can be transmitted only within the RTR facility in which they are defined. Application events cannot be sent between facilities or outside RTR.

Client and Server Interaction

For client and server applications to work together, you create a ClientTransactionController in the client application and a ServerTransactionController in the server application. These transaction objects communicate by using objects derived from the RTRData class.

RTR applications need to define an application-level protocol to pass data between client and server. From the point of view of a client or server application, the application protocol is just data. The data object encapsulates the application protocol as shown in Figure 1-4. In this example, a protocol is defined for sending data between a client and server application that processes book orders, as in the book ordering sample application. This data protocol includes fields for ISBN number, book-price, book-name, and author. These fields are contained in a buffer in an RTRData object.

The data protocol is encapsulated in a user-defined ApplicationProtocol class. The ApplicationProtocol class is an (derives from) RTRApplicationMessage, which is an (derives from) RTRStream, which is an (derives from) RTRData object that contains the application protocol in its buffer.

 

 

Figure 1-4: RTRData Encapsulation

 

The data classes are used by both client and server RTR applications. When applications want to send or receive data, they specify an RTRData-derived object.

Figure 1-5 illustrates client/server deployment and interaction. The numbered steps represent client logic within the client application and server logic within the server application. For a more detailed description of transactional messaging, see the RTR Application Design Guide.

Figure 1-5: Client/Server Interaction

An RTR transaction processing system consists of separate client applications and server applications. This example demonstrates a client sending a message to the server and the server responding, but the server calls the first Receive. The logical interaction between client and server is as follows:

  1. Call Receive from an RTRServerTransactionController object to obtain an RTRApplicationMessage object from the client. (The server first creates an RTRServerTransactionController object and then calls Receive.)
  2. Create a transaction in the RTRClientTransactionController object by calling StartTransaction.
  3. Create an RTRApplicationMessage object (or one derived from RTRApplicationMessage).
  4. Send the RTRApplicationMessage object to the server and wait for a message from the server by calling SendApplicationMessage.
  5. Process the data in the server application.
  6. Send an RTRApplicationMessage object from the server back to the client by calling SendApplicationMessage.

For more information on client and server messaging, see the RTR Application Design Guide.

The Class Factory

An instance of the class RTRClassFactory is an object that creates other data objects. The class RTRClassFactory has four methods:

Client and server transaction controllers use the class factory when receiving a message or event. Every transaction controller has a class factory. If the application does not register its own, a default is provided.

When the application calls Receive, the transaction controller determines what kind of message or event is about to be received, and then calls the appropriate method in the application-derived and registered class factory object (for example, CreateRTRMessage). This method creates the appropriate data object (for example, an RTRMessage object) and returns it to the transaction controller. The transaction controller copies the incoming data into the data object returned from the class factory and returns back to the application's call to Receive().

Applications can override the methods of the RTRClassFactory and return their own customized versions of the data classes.

 

 

 

Receiving an Application Message

Typical client requests processed by a server application are sent and received as RTRApplicationMessage objects. The most common method for implementing business logic data protocols is deriving from the RTRApplicationMessage class. In Figure 1-6, AM represents an incoming application message.

Figure 1-6: Receiving an Application Message

In Figure 1-6:

  1. An application calls a transaction controller Receive (for example, RTRServerTransactionController::Receive) to receive a message or event (AM, in the above figure).
  2. The transaction controller determines what kind of message or event is to be received (in this case, an application message) and calls the appropriate method in the registered RTRClassFactory object (for example, CreateRTRApplicationMessage).
  3. The RTRClassFactory object CreateRTRApplicationMessage method creates the appropriate data object (in this case, an RTRApplicationMessage object) and returns it to the transaction controller.
  4. The application processes the message according to the application implementation.

 

 

Receiving a User-Defined Application Message

User-defined application messages are sent and received as RTRApplicationMessage objects. In Figure 1-7, AM represents an incoming application message.

Figure 1-7: Receiving a User-Defined Application Message

In Figure 1-7:

  1. An application calls a transaction controller Receive (for example, RTRServerTransactionController::Receive) to receive a message or event (AM, in the above figure).
  2. The transaction controller determines what kind of message or event is to be received (in this case, an application message) and calls the appropriate method in the application-derived and registered ABCClassFactory object (for example, CreateApplicationMessage).
  3. The ABCClassFactory object CreateApplicationMessage method creates the appropriate data object (in this case, an ABCOrder object) and returns it to the transaction controller.
  4. The application processes the message according to the application implementation.

Note that the derived class factory does not have to handle all the messages. It is only handling the application message (AM) and taking all of the other default methods (for example, CreateRTRMessage).

 

 

Stream Classes

For an added level of functionality, the RTRStream data class allows for easier access to the data passed between the client and server applications. This class provides methods with which you can read from and write to the data buffer contained in RTRData. With these methods, maintaining offset into the buffer is automatic.

The RTRStream class allows the serialization and deserialization of objects. For example, if a client application called,

RTRStream::WriteToStream("WarandPeace");

RTRStream::WriteToStream("Tolstoy");

and a server then called,

RTRStream::ReadFromStream(pString1);

RTRStream::ReadFromStream(pString2);

pString1 would point to "WarandPeace" and after the second read, pString2 would point to "Tolstoy."

For large amounts of data to be sent and received, a WriteToStream method takes a void pointer to the length of the buffer.

Application Classes Summary

Figure 1-8 illustrates the client, data, and server classes in the application classes and shows their parallelism. Data classes are common to both client and server applications.

Figure 1-8: Application Classes

 

Table 1-1 shows application class categories and their descriptions. Table 1-2 lists the application data classes that are common to both client and server applications. Except for data classes, the class categories describe the characteristics of the associated client and server classes (for example, the Transaction Controller class category in Table 1-1 describes the RTRServerTransactionController and RTRClientTransactionController classes). For detailed descriptions of individual foundation classes and their associated methods, see the Application Classes chapter of this manual.

Table 1-1: Application Class Category Descriptions

Class Category

Description

Transaction Controller

The transaction controller manages each transaction and also manages the messages and events associated with that transaction.

  • Has client and server versions.
  • Manages each RTR transaction (1 transaction controller for each transaction.).
  • Controls at most one active transaction at a time.
  • Can process many sequential transactions.

Transaction Properties

The RTRTransactionProperties class:

  • Has client and server versions.
  • Can be used by new or existing applications.
  • Includes:
  • GetTransactionState.
  • SetTransactionState.
  • GetInvocationType.

Event Handlers

Use RTREventHandler classes to obtain information about a transaction such as whether a server is primary, standby or shadow.

The RTREventHandler class:

  • Has client and server versions.
  • Provides default implementation for every event.
  • Enables the application to override only the events it wants to
    process.
  • Can be extended to have application-specific handlers such as OnProcessOrder.

You must register an event handler with the RegisterHandlers method
in the TransactionController class.

Message Handlers

Message handlers can be used for all transactions and all application data.

The RTRMessageHandler class:

  • Has client and server versions.
  • Provides default implementation for every message.
  • Enables an application to override only the messages it wants to
    process.
  • Can be extended to have application-specific handlers.

RTRMessageHandler lets you override only messages you want to use. For example, OnApplicationMessage can be implemented with business-logic-specific objects such as OnStockBuy or OnStockSell.

 

Table 1-2: Data Class Descriptions

Class Category

Description

RTRMessage

The RTRMessage class:

  • Holds an RTR Message.
  • Derives from the RTRData class.
  • Is generated internally by RTR.

If an application has not registered a class factory, the application calls
the default class factory to allocate this object. The application:

  • Calls the Dispatch method to send this message to the
    appropriate handler.
  • Can optionally derive from RTRMessage to create a more business-
    specific class.

RTREvent

The RTREvent class:

  • Holds an RTR Event.
  • Derives from the class RTRData.
  • Is generated internally by RTR.

If an application has not registered a class factory, the application calls
the default class factory to allocate this object. The application:

  • Calls the Dispatch method to send this message to the appropriate
    handler.
  • Can optionally derive from RTREvent to create a more business-specific class.

RTRData

The RTRData class is used to send and receive messages and events.
It is the abstract base class for the following four data classes:

  • RTREvent
  • RTRMessage
  • RTRApplicationEvent
  • RTRApplicationMessage

RTRApplicationMessage

  • Holds an Application Message.
  • Derives from class RTRStream.
  • Is generated by a C++ API application.
  • Can be treated as a stream to write and read the state of a higher
    level object.

The application:

  • Calls the Dispatch method to send this message to the appropriate
    handler.
  • Can optionally derive from RTRApplicationMessage to create a
    more business-specific class.

RTRApplicationEvent

  • Holds an application Event.
  • Derives from the class RTRStream.
  • Is generated by a C++ API application.
  • Can be treated as a stream to write and read the state of a higher
    level object.

The application:

  • Calls the Dispatch method to send this message to the appropriate
    handler.
  • Can optionally derive from RTRApplicationMessage to create a
    more business-specific class.

RTRStream

The RTRStream class:

  • Derives from and extends the RTRData class
  • Allows RTR applications to issue multiple read and write requests
    to the memory buffer (managed by RTR).
  • Automatically handles buffer pointer management
  • Can be used to serialize and deserialize objects through RTR.

RTRClassFactory

The RTRClassFactory class creates instances of the data classes:

  • RTRMessage
  • RTREvent
  • RTRApplicationMessage
  • RTRApplicationEvent

An application registers its own class that is derived from the
RTRClassFactory and returns its own business level objects. If an
application does not register a customized version, by default, a class
factory object is internally created.

 

 

 

Management Classes

Management classes manage the environment in which an RTR application executes, not the business-logic infrastructure of the application. This allows you to do in a program what formerly had to be done at the system management command level.

Facility Management

Managing facilities is based on three concepts provided as separate foundation classes:

A facility manager creates and deletes facilities, and adds and removes facility members based on facility name.

Facility properties represent the information and properties of a single facility.

Facility members represent the individual members of a particular facility. A facility member is both a role and a node combined, because a node can have more than one role. For example, a nodename can represent three members by being defined three times with the same node but with different roles (backend, frontend, router).

For general information on RTR facilities, see RTR Getting Started and the RTR System Manager's Manual.

Partitions and Key Segments

One of the benefits of the routing capability in RTR is that it enables you to partition your data across multiple servers and nodes for increased performance. Within an application, the partition determines how messages are routed from clients to servers. RTR routes messages to the correct partition on the basis of an application-defined key.

The contents of a message determine its destination. The router tracks the location of data partitions and sends client messages to the appropriate server for processing. The routing key, or key segment, is embedded within the RTR message.

The foundation classes provide the object-oriented framework to implement data partitioning with the following classes:

A partition manager creates and deletes partitions, and returns properties for individual partitions based on partition name.

Partition properties represent individual partitions within RTR and provide statistics for a partition.

A key segment object defines the range of a partition.

An RTRKeySegment object specifies a data key range and is associated with a partition when a Partition Manager creates a partition.

Figure 1-9 illustrates the relationship between RTR entities and partition classes. Partition classes refer to an RTR partition. As the figure illustrates, the actual partition resides in RTR, not in the foundation class objects. Methods within the partition classes can create and delete partitions, and get partition properties for the RTR partitions.

Figure 1-9: Partition Objects and RTR

 

 

Management Classes Descriptions

Figure 1-10 shows the management class categories and their classes. These classes can be used in new applications or integrated into existing legacy applications.

Figure 1-10: Management Classes

With the management classes, you can create a facility or a partition programmatically instead of using the command language interface (CLI). For legacy applications, you can write management routines to create your application environment in an existing RTR C-language application.

Facility, management, and partition information exists in RTR. The management classes access the information from RTR.

Table 1-3 describes the management classes. For detailed descriptions of individual classes and their associated methods, see the Management Classes chapter of this manual.

 

 

Table 1-3: Management Class Descriptions

Class

Description

RTRFacilityManager

Is used to manage the creation, deletion, and viewing of facilities
based on facility name (existing RTR programs use facility names).

RTRFacilityMember

Represents a member of a particular facility. The member can be any
node in the facility, including the local node.

Knows the relationship to the local node.

Provides member functions to evaluate connectivity. For example, IsConnectedToLocalNode returns a boolean return to a query such as:
"Is node A connected to me?"

RTRFacilityProperties

Represents a single facility that exists within RTR.

Knows other members in the facility.

RTRPartitionManager

Manages the creation and deletion of partitions based on
partition name.

RTRKeySegment

Defines and represents the key range of a partition associated with
an RTR server.

RTR

The RTR class represents RTR on the local node and performs
actions that apply to RTR as a whole including:

  • Starting RTR.
  • Stopping RTR.
  • Creating a journal.
  • Deleting a journal.
  • Starting a web server.
  • Stopping a web server.

RTRCounter

Enables an application to define and manipulate a counter within
RTR. They can be used within monitor screens to mix RTR and
application diagnostic information. RTRCounter is the base
class for:

  • RTRStringCounter
  • RTRSignedCounter
  • RTRUnsignedCounter

RTRBackendPartitionProperties

Supplies information about a partition, once it has been created.

Can be used by new or existing applications.

Can be used to obtain information on partitions created at the
command line or by the RTRPartitionManager.

Represents a single partition that exists within RTR. Since a
partition property object is not an actual partition but an object that
knows the properties of an RTR partition, if the partition is deleted,
the partition class points to nothing and returns an error.

Provides statistics for a partition.

 

Processing Models

You can use either of two processing models to implement client and server applications. Depending on which processing model you use, you implement the classes differently. The two processing models are:

Processing mechanisms are different for the polling and event-driven models. With the polling model, when receiving the data object, obtaining the RTR message value requires a GetMessageType call. With event-driven processing, if you are using the handlers, a Receive returns your states. Event-driven is an addition to the primitive polling mechanism. By adding a call to Dispatch in the polling mechanism in the application, you can enable default processing for all messages and events.

Table 1-4 compares the two processing models. These comparisons apply to both client and server. The sample application and code examples in this book use event-driven processing in server applications, and polling in client applications.

 

 

Table 1-4: Transaction Processing Models Compared

Processing
Method

What You Get

Programming Logic

Message and Event Handling

Event-Driven

Default handling of all RTR messages and events.

Create a loop containing Receive() and Dispatch() calls.

Messages and Events are handled by the MessageHandler and EventHandler objects.

Polling

RTRData methods that allow for user-implemented detection of incoming data and development of message and event handling.

Use RTRData methods to detect incoming data types. Develop logic to handle all possible messages and events.

User-implemented logic in place of MessageHandler and EventHandler classes.

 

Event-Driven Model

Figure 1-11 shows the steps in the event-driven model of transaction processing as used in a server application.

Figure 1-11: Event-Driven Server Processing

In the event-driven model, the application is informed when there is something for it. RTR automatically sends messages to the server and the server runs a transaction, using the Receive and Dispatch methods within a while loop. Business logic resides in the message and event handlers. The event-driven model is the recommended method for implementing server applications.

As shown in Figure 1-11, the sequence of operations is as follows:

  1. Create an environment that has one or more partitions that are defined in key segments.
  2. Create a TransactionController object.
  3. Create the handler classes derived from base classes. Business logic resides in the message and event handlers.
  4. Call Register methods to register facility, class factory, partition, and handlers. This internal hookup creates a mapping to the message and event handlers.
  5. Start to receive information (messages or events) for the partition registered to the ServerTransactionController by calling Receive, a method on the ServerTransactionController. The class factory creates a data object on the Receive call. The Transaction Controller receives the data object.
  6. Call Dispatch. Dispatch knows which handler to go to.
  7. User-implemented logic and methods are stored in the data object. Checking for RTR-generated data, retrieving messages, and retrieving events are all done for you automatically, if you call Dispatch. For example, on a Receive call, if the message is rtr_mt_msgn, then calling Dispatch calls OnApplicationMessage by default. OnApplicationMessage is a method in the RTRServerMessageHandler and RTRClientMessageHandler classes.

    Business logic is typically implemented in the server message handler. However, you can implement business logic in other ways as well.

  8. Loop for next event.

Event-Driven Processing

Using the event-driven model implements the following mechanism:

  1. Receive within a loop to receive a message or event.
  1. Call Dispatch.

The Data Object is passed on this call. All handler methods have two parameters: a message type, and a pointer to the TransactionController from which the message came. Data Objects, which are stateless, are not tied to a TransactionController; they can be handled by different TransactionControllers. Thus, using a TransactionController does not restrict client applications.

  1. By default, the RTRData object automatically accesses the appropriate Handler by the appropriate method, depending on the message or event with the RTRClassFactory class. For example, if RTRData contains RTR message type rtr_mt_msgn, then Dispatch calls OnApplicationMessage(RTRApplicationMessage).
  2. The Data Object is processed within the appropriate Handler. For example, the RTRData object containing rtr_mt_msgn is processed by OnApplicationMessage. This is where the business logic is typically implemented.

This sequence is shown in Figure 1-12.

Figure 1-12: Event-Driven Processing Example

 

Message and Event Handling

This section provides event and message handling examples that are processed based on what RTR message or event is received on a Receive call. Depending on the message received, the subsequent process is different, as shown in Table 1-5.

Table 1-5: Message and Event Handling Examples

If the message received is:

Then:

rtr_mt_msgn

The Data Object goes to the Message Handler by the OnApplicationMessage(Data Object) method. Then, in the Message Handler, the Data Object is processed by OnApplicationMessage.

rtr_mt_rejected

The Data Object goes to the Message Handler using the OnRejected(Data Object) method. Then, in the Message Handler, the Data Object is processed by OnRejected.

rtr_mt_prepare

The Data Object is dispatched to be handled internally. Application business logic does not need to know about RTR Prepares. In the C++ API, Prepares are transparent.

EVTNUM_SRPRIMARY

The Data Object goes to the Event Handler using the OnServerIsPrimary(Data Object) method. Then, in the Event Handler, the Data Object is processed by OnServerIsPrimary.

 

RTRMessageHandler and RTREventHandler are the default handlers. Processing is done by an application's derived business logic. Default handlers do not keep state, so the application must return to BackendPartitionProperties to get state.

Event-Driven Example

Example 1-1 illustrates the looping implementation for event-driven processing.

Example 1-1: Receive Loop

ServerTransactionController ServerTransactionController;

RTRData *pDataBeingReceived = NULL;

while (true)

{

// Receive some data

ServerTransactionController.Receive(&pDataBeingReceived);

// No need to determine what we received.
// Just call Dispatch();

pDataBeingReceived->Dispatch();

}

Polling Model

Figure 1-13 shows the steps in the polling model of transaction processing as used in a client application.

Figure 1-13: Polling Processing Model

 

The polling model processing steps are:

  1. Create an environment that has one or more partitions defined in key segments.
  2. Create a transaction controller object.
  3. Call Register methods to register facility (for client) and partitions (for server) and class factory.
  4. Call Receive to check the data object.
  5. In place of Dispatch, start gathering information for the partition on RTR by calling RTRData methods such as IsApplicationMessage, IsMessage, and IsEvent (for a full listing of boolean RTRData methods, see the Application Classes chapter of this manual) to determine what type of data is being received in order to process it.
  6. User-implemented logic handles all possible messages, events, and serialized objects using RTRData methods.

  7. Call Receive again.

In the polling model, you create a receive loop to poll for incoming data. Messages or events are received one at a time, and Register does not connect message and event handlers. The server asks RTR for a request.

You can still check the data object and code tasks as follows:

As Figure 1-13 illustrates, in common with the event driven model, you use a subset of the same objects, but Register does not connect the message and event handlers.

 

 

Polling Model Example

Example 1-2 illustrates an implementation for the polling model of processing. As this example illustrates, the flow is controlled by the object that is polling for a message or event from RTR with Receive.

Example 1-2: Polling Model Example

ServerTransactionController ServerTransactionController;

RTRData *pDataBeingReceived = NULL;

while (true){

// Receive some data

ServerTransactionController.Receive(&pDataBeingReceived);

// Since handlers are not being used, determine what is
// received. Application-generated message or event.
// RTR-generated message or event.

if (true = pDataBeingReceived->IsApplicationMessage())

{
// Process accordingly

}

else
if (true = pDataBeingReceived->IsApplicationEvent())

{
// Process accordingly

}

else

if (true = pDataBeingReceived->IsRTRMessage())

{
// Process accordingly

}

else

if (true = pDataBeingReceived->IsRTREvent())

{
// Process accordingly

}

}

 

Base Classes Message and Event Mapping

The foundation class message and event handler methods are provided in base classes. You derive from them and choose which ones to use in your implementation. Base handlers are used by default, if you do not derive from them.

Figure 1-14 illustrates RTR messaging between client and server. RTR messages are contained in the data object passing between the client and server. With event-driven processing, the class factory creates the appropriate data object.

Figure 1-14: RTR Messaging Between Client and Server Applications

To connect, the client registers a facility and the server registers a facility and a partition. The client transaction ends with rtr_mt_accepted or rtr_mt_rejected. The server transaction ends with the AcknowledgeTransactionOutcome method.

When Dispatch is called, certain handlers are called for transactions on the client and server, as shown in the following tables.

 

 

Client Messages

When Dispatch is called, certain handlers are called for transactions on the client, as shown in Table 1-6.

Table 1-6: Client Handlers by Message Type

When the RTR Message Type is:

Contained in:

The RTRClientMessageHandler Call is:

rtr_mt_accepted

RTRMessage

OnAccepted

rtr_mt_reply

RTRApplicationMessage

OnApplicationMessage

rtr_mt_rttosend

RTRMessage

OnReturnToSender

rtr_mt_prepared

RTRMessage

OnAllPreparedTransaction

rtr_mt_rejected

RTRMessage

OnRejected

 

For example, using the event-driven processing model, when RTRData contains rtr_mt_reply, by default, the RTRApplicationMessage Dispatch method calls OnApplicationMessage.

Client Events

When Dispatch is called, certain handlers are called for transactions on the client, as listed in Table 1-7.

Table 1-7: Client Handlers by Event for RTREvent

When the RTR Event Number is:

The RTRClientEventHandler Call is:

RTR_EVTNUM_FACDEAD

OnFacilityDead

RTR_EVTNUM_FACREADY

OnFacilityReady

RTR_EVTNUM_FERTRGAIN

OnFrontendGainedLinkToRouter

RTR_EVTNUM_FERTRLOSS

OnFrontendLostLinkToRouter

RTR_EVTNUM_RTRBEGAIN

OnRouterGainedLinkToBackend

RTR_EVTNUM_RTRBELOSS

OnRouterLostLinkToBackend

RTR_EVTNUM_KEYRANGEGAIN

OnNewKeyRangeAvailable

RTR_EVTNUM_KEYRANGELOSS

OnKeyRangeNoLongerAvailable

 

For example, with the event-driven processing model, when RTRData contains RTR_EVTNUM_FACREADY, by default, the RTREvent Dispatch method calls OnFacilityReady.

Server Messages

When Dispatch is called, certain handlers are called for transactions on the server side, as listed in Table 1-8.

Table 1-8: Server Handlers by Message Type

When the RTR Message Type is:

Contained in:

The RTRServerMessageHandler Call is:

rtr_mt_accepted

RTRMessage

OnAccepted

rtr_mt_msg1

RTRApplicationMessage

OnInitialize

OnApplicationMessage

rtr_mt_msg1_uncertain

RTRApplicationMessage

OnUncertainTransaction

rtr_mt_msgn

RTRApplicationMessage

OnApplicationMessage

rtr_mt_prepare

RTRMessage

OnPrepareTransaction

rtr_mt_rejected

RTRMessage

OnRejected

 

For example, with the event-driven processing model, by default when RTRData contains rtr_mt_msg1, the RTRServerMessageHandler first calls OnInitialize and then calls OnApplicationMessage. With the polling model, use IsMessage in place of Dispatch and implement GetMessageType to handle the message.

A typical series of Server messages processed for a Transaction in an RTRTransactionController object would be as follows:

OnInitialize

OnApplicationMessage

OnPrepareTransaction

OnAccepted

 

 

Server Events for RTREvent

When Dispatch is called, certain handlers are called for transactions on the server side, as listed in Table 1-9.

Table 1-9: Server Handlers by Event

When the RTR Event Number is:

The RTRServerEventHandler Call is:

RTR_EVTNUM_BERTRLOSS

OnBackendGainedLinkToRouter

RTR_EVTNUM_BERTRGAIN

OnBackendGainedLinkToRouter

RTR_EVTNUM_FACDEAD

OnFacilityDead

RTR_EVTNUM_FACREADY

OnFacilityReady

RTR_EVTNUM_RTRFEGAIN

OnFrontendGainedLinkToRouter

RTR_EVTNUM_RTRFELOSS

OnFrontendLostLinkToRouter

RTR_EVTNUM_SRSHADOWGAIN

OnServerGainedShadow

RTR_EVTNUM_SRSHADOWLOST

OnServerLostShadow

RTR_EVTNUM_SRRECOVERCMPL

OnServerRecoveryComplete

RTR_EVTNUM_SRPRIMARY

OnServerIsPrimary

RTR_EVTNUM_SRSECONDARY

OnServerIsSecondary

RTR_EVTNUM_SRSTANDBY

OnServerIsStandby

 

For example, with the event-driven processing model, by default, when RTRData contains RTR_EVTNUM_FACREADY, the RTRServerEventHandler calls OnFacilityReady. With the polling model, use IsEvent in place of Dispatch, and implement GetEventNumber to handle the event.

For more information, see the state diagrams in Appendix C of the RTR Application Design Guide.

 

 

Using the C++ API with Existing Applications

When working with existing RTR applications, you can integrate individual C++ foundation classes into existing client or server applications and also write new management routines that work with existing applications. With the C++ foundation classes, there are no migration issues. There is no need to rewrite existing code to integrate C++ foundation classes. Existing client and server applications are linked transparently by RTR .

In existing applications, objects defined in the application can point to instances of foundation classes.

These classes are designed to be used:

Objects defined in your application can point to instances of the foundation classes, and inherit the rich functionality within these base classes.

The C++ foundation classes provide a method for implementing RTR solutions that is easier to use than the C API. The C++ foundation classes:

Classes that Legacy Applications Can Use

Table 1-10 lists the classes that legacy RTR server applications can use to create and manage the environment in which RTR applications run. The second column of Table 1-10 lists the information required to implement instances of these classes.

Table 1-10: Foundation Classes for Legacy Applications

Class

Requires:

Setup class:

  • RTR

 

Nothing

Facility classes:

  • RTRFacilityManager
  • RTRFacilityMember

 

Facility Name

Facility Name

Partition classes:

  • RTRPartitionManager
  • RTRKeySegment

 

Nothing

Nothing

Property classes:

  • RTRClientTransactionProperties
  • RTRServerTransactionProperties
  • RTRBackendPartitionProperties
  • RTRFacilityProperties

 

TID (Transaction ID)

TID

Partition Name

Facility Name

Diagnostic class:

  • RTRCounter

Nothing (for new applications)

Group Name

 

Facility, management, and partition information exists in RTR. The methods within the management and property classes rely on attributes that RTR applications have.

For example, the diagnostic class RTRCounter relies on the following attributes for getting information:

These are all attributes found in RTR.

The RTRBackendPartitionProperties class relies on partition name and facility name; existing applications already know the partition name. This enables you to call methods, such as GetRetryCount, in this class by passing in a partition. For example:

RTRBackendPartitionProperties MyPartition("MyPartitionName");

MyPartition.GetRetryCount();

Encapsulating Application Protocols

Since foundation classes work with existing applications, the protocol for passing data has not changed. As Figure 1-15 illustrates, legacy applications and new applications both use the same protocol for passing data. Thus, all combinations of old and new clients and servers can communicate with each other.

Figure 1-15 C++ API into Existing Applications

 

The protocol manager represents an object that knows how to send and receive a protocol defined by the application. The protocol is your data. This is achieved by deriving a class from RTRData that knows how to store information (data) in it. RTRData does this by pointing to a buffer.

Figure 1-16 illustrates the data encapsulation in the protocol manager objects that are shown in Figure 1-15.

Figure 1-16: The Protocol Manager Object

 

 

For more information on defining a class that encapsulates an application protocol, see the Design and Implementation chapter of this manual.

Implementation Example

In the example shown in Figure 1-17, there is an existing server application and a new client application. To have your existing RTR legacy server application communicate with and obtain information from a new C++ client application, you do not need to integrate C++ foundation classes into your server application.

Figure 1-17: Legacy Application Example

Legacy applications do not have a TransactionController but with the RTRServerTransactionProperties and RTRClientTransactionProperties classes, you need only a TID (transaction identifier) to get state information. You obtain the TID with the existing RTR C API using the rtr_get_tid method. You can pass this TID into the RTRServerTransactionProperties and RTRClientTransactionProperties classes.

By using the rtr_get_tid method of the RTR C API to get the TID, you can pass this value to the new C++ API to construct a ServerTransactionProperties object, with this TID as the parameter (ServerTransactionProperties(TID)). Creating an application with this ServerTransactionProperties object enables you to call any member functions within the ServerTransactionProperties class, such as GetTransactionState and GetFacility.

Compiling and Linking your Application

All client and application programs must be written using C, C++, or a language that can use RTR C++ API calls. Include the RTR data types and error messages file rtrapi.h in your compilation so that it will be appropriately referenced by your application. For each client and server application, your compilation/link process is as follows:

  1. Write your application code using RTR calls.
  2. Use RTR data and status types for cross-platform interoperability.
  3. Compile your application code calling in rtrapi.h using ANSI C include rules. For example, if rtrapi.h is in the same directory as your C++ code, use with the following statement: #include "rtrapi.h".
  4. Link your object code with the RTR library to produce your application executable.

This process is illustrated in Figure 1-18. In this figure, Library represents the RTR C++ API shareable images (OpenVMS), DLLs (Win32), and shared libraries (UNIX).

Figure 1-18: RTR Compile Sequence

 

The following command lines show the sort of command lines that are needed to compile and link a C++ RTR application that uses the C++ foundation classes, with and without Posix or Microsoft threads. The parts of the command relating to RTR and the parts relating to threads are shown. You may need to specify library directories explicitly if the RTR header files and libraries are not installed in the same directory or in system directories. Note that the exact name of the RTR foundation classes shared library, DLL or shareable image file, and how it is referenced in a command line, varies slightly according to the conventions for the particular platform. Most compilers recognize the extensions .cc .cpp and .cxx for C++ source files.

$ cxx yourapp.cxx

$ cxxlink yourapp,sys$input/opt

librtrcpp/share

$

$ cxx yourapp.cxx

$ cxxlink yourapp,sys$input/opt

librtrcpp_r/share

$

> cl /c -D_MT yourapp.cpp

> link yourapp.obj /out:yourapp.exe rtrcppapi.lib

% cxx yourapp.cc -o yourapp -lrtrcpp

% cxx -pthread yourapp.cc -o yourapp -lrtrcpp

Compilers commonly used in developing RTR applications include those in the following table. For additional information, see the Reliable Transaction Router Software Product Description.

 

Operating System Compiler Compiler Version
Microsoft Windows Microsoft Visual C++ Version 6.0 SP4
OpenVMS Alpha Compaq C Version 6.2-006
OpenVMS Alpha Compaq C++ Version 6.2-035
OpenVMS VAX Compaq C Version 6.2-003
Sun Workshop Compilers Version 4.2
Tru64 UNIX Compaq C Version 6.3-126
Tru64 UNIX Compaq C++ Version 6.2-033