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:

It uses the default handler methods for:

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

  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:

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:

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:

An application can receive four data categories:

The four RTRData-derived classes are:

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:

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