hp Reliable Transaction Router
C++ Foundation Classes


Previous Contents Index

1.2.6 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: Receiving a User-Defined Application Message, 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 the all messages. It is only handling the application message (AM) and taking all of the other default methods (for example, CreateRTRMessage).

1.2.7 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.

1.2.8 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 channels, 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 The RTRApplicationMessage class:
  • 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 The RTRApplicationEvent class:
  • 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.

1.3 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:

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:

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


1.3.1 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 anynode 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.

1.4 Message Reception Styles

You can use either of two message reception styles or processing models to implement client and server applications. Depending on which processing model you use, you implement the classes differently. The two processing styles or 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.

1.4.1 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.
    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.
  7. 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.
  2. 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.
  3. 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).
  4. 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(); 
} 


Previous Next Contents Index