# hp Reliable Transaction Router
C++ Foundation Classes

Previous | Contents | Index

## 2.3.4 Examining RTRData Objects

You can check the contents of an RTRData object by calling any RTRData method such as IsMessage. The following example from the client application ABCOrderTaker illustrates how an application can retrieve and use the message from an RTRData derived object.

        while (OrderBeingProcessed == eTxnResult)
        {
        sStatus = Receive(&pResult);
        print_status_on_failure(sStatus);
        if ( true == pResult->IsRTRMessage())
        {
        // Check to see if we have a status for the transaction.
        // rtr_mt_accepted = Server successfully processed our request.
        // rtr_mt_rejected = Server could not process our request.
        sStatus = ((RTRMessage*)pResult)->GetMessageType(mtMessageType);
        print_status_on_failure(sStatus);
        if (rtr_mt_accepted == mtMessageType) return eTxnResult =
        OrderSucceeded;
        if (rtr_mt_rejected == mtMessageType) return eTxnResult =
        OrderFailed;
              }
            }
            return eTxnResult;

## 2.3.5 Sample Server Application

The following figure illustrates the objects within the ABCOrderProcessor server application. Each of the four server classes derives from the associated base classes.

Figure 2-4 Sample Server Application

The implementation of ABCOrderProcessor uses default construction and destruction and then follows the steps described earlier in this chapter to create a server application.

Processing Method

The sample server application implements the event-driven processing model in ProcessIncomingTransactions. Implementation of ProcessIncomingTransactions is as follows:

1. Create a transaction controller to receive incoming messages and events from a client.
2. Create an environment where the server can run, then Register with RTR the partitions, handler classes, class factory and objects using the transaction controller:

           sStatus = RegisterFacility(ABCFacility);
           print_status_on_failure(sStatus);
           // ABC Partition
           sStatus = RegisterPartition(ABCPartition1);
           print_status_on_failure(sStatus);
           sStatus = RegisterPartition(ABCPartition2);
           print_status_on_failure(sStatus);
           // ABC Class Factory
           sStatus = RegisterClassFactory(&m_ClassFactory);
           print_status_on_failure(sStatus);
           // ABC Handlers
           sStatus = RegisterHandlers(&m_rtrHandlers,&m_rtrHandlers);
           print_status_on_failure(sStatus);
           return;
       // Create the environment :
       void ABCOrderProcessor::CreateRTREnvironment()
       {
              rtr_status_t sStatus;
               // If RTR is not already started then start it now.
           StartRTR();
               // Create a Facility if not already created.
           CreateFacility();
       // Create a partition that processes ISBN numbers in the range 0 -
       // 99
               unsigned int low = 0;
               unsigned int max = 99;
           RTRKeySegment KeyZeroTo99(  rtr_keyseg_unsigned,
                                       sizeof(int),
                                       0,
                                       &low,
                                       &max );
       RTRPartitionManager PartitionManager;
       sStatus = PartitionManager.CreateBackendPartition( ABCPartition1,
                                                          ABCFacility,
                                                          KeyZeroTo99,
                                                          false,
                                                          true,
                                                          false);
               print_status_on_failure(sStatus);
       // Create a partition that processes ISBN numbers in the range 100 -
       // 199
               low = 100;
               max = 199;
           RTRKeySegment Key100To199(  rtr_keyseg_unsigned,
                                       sizeof(int),
                                       0,
                                       &low,
                                       &max );
           sStatus = PartitionManager.CreateBackendPartition(  ABCPartition2,
                                                               ABCFacility,
                                                               Key100To199,
                                                               false,
                                                               true,
                                                               false);
               print_status_on_failure(sStatus);
           }

3. Instantiate the handler class ABCSHandlers.
4. Create an RTRData object to hold each incoming message or event. This object will be reused.

           // Start processing orders.
           abc_status sStatus;
           RTRData *pOrder = NULL;

5. Continually loop, receiving messages and dispatching them to the handlers:

           while (true)
               {
           // Receive an Order
                   sStatus = Receive(&pOrder);
                      print_status_on_failure(sStatus);
                   if(ABC_STS_SUCCESS != sStatus) break;
           // if we can't get an Order then stop processing.
           // Dispatch the Order to be processed
                   sStatus = pOrder->Dispatch;
                   print_status_on_failure(sStatus);
           // Exception handling:
           // Check to see if there were any problems processing the order.
           // If so, let the handler know to reject this transaction when
           // asked to vote.
                  CheckOrderStatus(sStatus);
           ...
           }

6. Check to see if there were any problems processing the order. If so, let the handler know that this transaction is to be rejected when asked to vote.

           void ABCOrderProcessor::CheckOrderStatus (abc_status sStatus)
           if (sStatus == ABC_STS_ORDERNOTPROCESSED)
               {
           // Let the handler know that the current txn should be rejected
                   GetHandler()->OnABCOrderNotProcessed();
               };

7. Cleanup. Delete this order that was allocated by the class factory. In the sample application, the class factory returns a separate instance of an order each time it is called.

           delete pOrder;

Server Message and Event Handler

The ABCOrderProcessor server application includes the derived class ABCSHandler for event-driven message and event handling. As Figure 2-5 illustrates, it combines both handlers into one handler class by deriving from both RTRServerEventHandler and RTRServerMessageHandler classes.

Figure 2-5 Sample Server-Handler-Derived Class

The ABCSHandler class overrides the following four handler methods:

- OnApplicationMessage
- OnPrepareTransaction
- OnAccepted
- OnRejected

It uses the default handler methods for:

- OnInitialize
- OnUncertainTransaction

In addition to the above over-ridden methods, it also contains an application-defined method to handle exceptions, OnABCOrderNotProcessed().

## 2.3.6 Sample Client Application

Figure 2-6 illustrates the ABCOrderTaker sample application. This example uses the polling receive processing model, not message or event handlers.

Figure 2-6 Sample Client Application

The client application header file ABCOrderTaker.h declares the interface for the ABCOrderTaker class. The file ABCOrderTaker.cpp provides the implementation.

In addition to the default constructor and destructor, there are two methods within class ABCOrderTaker:

- SendOrder
- Register
- DetermineOutcome

SendOrder

1. Create the environment where ABCOrderTaker is to run by registering a facility:

           sStatus = RegisterFacility(ABCFacility);
                  print_status_on_failure(sStatus);
                  if(RTR_STS_OK == sStatus)
                  {
                      m_bRegistered = true;
                  }

2. Create a Transaction Controller to receive incoming messages and events from a client.

           ABCOrderTaker OrderTaker;

3. Send the server a message:

           sStatus = SendApplicationMessage(pOrder);
               print_status_on_failure(sStatus);

4. Since we have successfully finished our work, tell RTR that we are willing to accept the transaction. Let RTR know that this is the object being sent and that we are done with our work:

           sStatus = AcceptTransaction();
           print_status_on_failure(sStatus);

5. Determine if the server successfully processed the request

           eTxnResult = DetermineOutcome();
           return true;

# 2.4 RTR Applications in a Multiplatform Environment

Applications using RTR in a multiplatform (mixed endian) environment with non-string application data must tell RTR how to marshall the data both for the destination of the application data being sent and the application data itself. This description is supplied as the `rtr_const_msgfmt_t` argument to:

- RTRClientTransactionController::SendApplicationMessage
- RTRServerTransactionController::SendApplicationMessage
- RTRClientTransactionConrtroller::SendApplicationEvent
- RTRServerTransactionController::SendApplicationEvent

The default (that is, when `rtr_const_msgfmt_t` is supplied) is to assume the application message is string data.

## 2.4.1 Defining a Message Format

The `rtr_const_msgfmt_t` string is a null-terminated ASCII string consisting of a number of field-format specifiers:

    [field-format-specifier ...]

The field-format specifier is defined as:

    %[dimension]field-type

where:

Field | Description | Meaning
--- | --- | ---
% | Indicates a new field description is starting. |
dimension | Is an optional integer denoting array cardinality (default 1). |
field-type | Is one of the following codes: |
| UB | 8 bit unsigned byte
| SB | 8 bit signed byte
| UW | 16 bit unsigned
| SW | 16 bit signed
| UL | 32 bit unsigned
| SL | 32 bit signed
| C | 8 bit signed char
| UC | 8 bit unsigned char
| B | boolean

For example, consider a data object containing the following:

        unsigned int m_uiISBN;
        unsigned int m_uiPrice;
        char m_szTitle[ABCMAX_STRING_LEN];
        char m_szAuthor[ABCMAX_STRING_LEN];

The `rtr_const_msgfmt_t` for this object could be ("%UL%SL%12C%12C").

The transparent data-type conversion of RTR does not support certain conversions (for example, floating point). These should be converted to another format, such as character string.

# Chapter 3
Application Classes

The RTR C++ API major application classes are:

- Server classes
- Client classes
- Data classes

This chapter describes these major classes in the above order. Within each major class, each class is described in alphabetical order. Within each class, all of its inherited methods are described in alphabetical order.

RTRData-derived classes are used for passing data between client and server applications.

An application can send two data categories:

- Application-defined messages
- Application-defined events.

An application can receive four data categories:

- Application-defined messages
- Application-defined events
- RTR-defined messages
- RTR-defined events

The four RTRData-derived classes are:

- RTRApplicationMessage
- RTRApplicationEvent
- RTRMessage
- RTREvent

An RTRClassFactory object creates these four classes. The RTR application does not need to register a class factory with a transaction controller, but if it does, it can customize how the objects are allocated including allocating a class that is derived from any of the four data classes above.

# 3.1 Server Classes

The server application classes are:

- RTRServerEventHandler
- RTRServerMessageHandler
- RTRServerTransactionController
- RTRServerTransactionProperties

# 3.2 RTRServerEventHandler

This class defines event handlers for all potential events that an RTR server application can receive. Each handler has a default behavior. Applications should override those member functions for which they want to perform application-specific processing.

Note Applications can extend this class by deriving from it and adding their own application-level event handlers.

For further information see RTRData::Dispatch().

# RTRServerEventHandler Class Members

Construction

Method | Description
--- | ---
RTRServerEventHandler() | Constructor.
~RTRServerEventHandler() | Destructor.

Operations

Method | Description
--- | ---
OnApplicationEvent(RTRApplicationEvent, RTRServerTransactionController) | The application has generated an event for the server.
OnBackendGainedLinkToRouter(RTREvent, RTRServerTransactionController) | Default handler for the event where a backend link to the current router has been established.
OnBackendLostLinkToRouter(RTREvent, RTRServerTransactionController) | Default handler for the event where the backend link to the current router has been lost.
OnFacilityDead(RTREvent, RTRServerTransactionController) | Default handler for the event where the facility is no longer operational.
OnFacilityReady(RTREvent, RTRServerTransactionController) | Default handler for the event where the facility has become operational.
OnRouterGainedLinkToFrontend(RTREvent, RTRServerTransactionController) | Default handler for the event where a frontend link to the current router has been established.
OnRouterLostLinkToFrontend(RTREvent, RTRServerTransactionController) | Default handler for the event where a frontend link to the current router has been lost.
OnServerGainedShadow(RTREvent, RTRServerTransactionController, (rtr_const_parnam_t)) | The server gained its shadow partner.
OnServerIsPrimary(RTREvent, RTRServerTransactionController) | Default handler for the event where the server is in primary mode.
OnServerIsSecondary(RTREvent, RTRServerTransactionController) | Default handler for the event where the server is in secondary mode.
OnServerIsStandby(RTREvent, RTRServerTransactionController) | Default handler for the event where the server is in standby mode.
OnServerLostShadow(RTREvent, RTRServerTransactionController, (rtr_const_parnam_t)) | The server lost its shadow partner.
OnServerRecoveryComplete(RTREvent, RTRServerTransactionController) | Default handler for the event where the server has completed recovery.

# OnApplicationEvent()

## RTRServerMessageHandler::OnApplicationEvent();

## Prototype

>     virtual rtr_status_t OnApplicationEvent (RTRApplicationEvent
>                                              *pRTRApplicationEvent,
>                                              RTRServerTransactionController
>                                              *pController)
>     {
>       return RTR_STS_OK;
>     }

## Parameters

> ### pRTRApplicationEvent

> Pointer to an RTRApplicationEvent object that describes the message which is being processed.

> ### pController

> Pointer to the transaction controller within which this event was received.

## Description

> The pRTRApplicationEvent parameter contains an application event sent to it by the client application.

> Override this method if your application is to receive an indication that this event has occurred.

> The default behavior is that the handler dismisses the notification.

## Example

>     void CombinationOrderProcessor::OnApplicationEvent ( RTRApplicationEvent
>     *pApplicationEvent, RTRServerTransactionController *pController)
>     {
>     // This handler is called by RTR when the client has sent an event.
>     }

# OnBackendGainedLinkToRouter()

## RTRServerEventHandler::OnBackendGainedLinkToRouter();

## Prototype

>     virtual rtr_status_t OnBackendGainedLinkToRouter(RTREvent * pRTREvent,
>                                         RTRServerTransactionController
>                                         *pController)
>     {
>     return RTR_STS_OK;
>     }

## Parameters

> ### pRTREvent

> Pointer to an RTREvent object that describes the RTR-generated event being processed.

> ### pController

> Pointer to the transaction controller within which this event was received.

## Description

> This method provides the default handler for the event where a backend link to the current router has been established.

> The server application is receiving an RTR-generated event. RTREvent contains the RTR-defined event number RTR_EVTNUM_BERTRGAIN (104) and any associated data.

> Override this method if your application is to receive an indication that this event has occurred.

## Example

>     void RTRServerEventHandler::OnBackendGainedLinkToRouter( RTREvent
>                *pEvent, RTRServerTransactionController *pController )
>     {
>     }

# OnBackendLostLinkToRouter()

## RTRServerEventHandler::OnBackendLostLinkToRouter();

## Prototype

>     virtual rtr_status_t OnBackendLostLinktToRouter(RTREvent * pRTREvent,
>                              RTRServerTransactionController *pController)
>     {
>     return RTR_STS_OK;
>     }

## Parameters

> ### pRTREvent

> Pointer to an RTREvent object that describes the RTR-generated event being processed.

> ### pController

> Pointer to the transaction controller within which this event was received.

## Description

> This method provides the default handler for the event where the backend link to the current router has been lost.

> The server application is receiving an RTR-generated event. RTREvent contains the RTR-defined event number RTR_EVTNUM_BERTRLOSS (105) and any associated data.

> Override this method if your application is to receive an indication that this event has occurred.

## Example

>     void RTRServerEventHandler::OnBackendLostLinkToRouter( RTREvent
>                *pEvent, RTRServerTransactionController *pController )
>     {
>     }

# OnFacilityDead()

## RTRServerEventHandler::OnFacilityDead();

## Prototype

>     virtual rtr_status_t OnFacilityDead(RTREvent * pRTREvent,
>                                    RTRServerTransactionController *pController)
>     {
>      return RTR_ST_OK;
>     }

## Parameters

> ### pRTREvent

> Pointer to an RTREvent object that describes the RTR-generated event being processed.

> ### pController

> Pointer to the transaction controller within which this event was received.

## Description

> This method provides the default handler for the event where the facility is no longer operational.

> The server application is receiving an RTR-generated event. RTREvent contains the RTR-defined event number RTR_EVTNUM_FACDEAD (97) and any associated data.

> Override this method if your application wants to receive an indication that this event has occurred.

## Example

>     void RTRServerEventHandler::OnFacilityDead( RTREvent *pEvent,
>     RTRServerTransactionController *pController )
>     {
>     }

Previous | Next | Contents | Index