Reliable Transaction Router
Application Programmer's Reference Manual


Previous Contents Index

2.11.2 Developing Applications to Use Events

Subscribing to Events

RTR Events can be used for triggering special application processing based on a change in RTR system status, or for sending notification to the system operator after certain application or RTR conditions that require intervention.

User Events can be used for actions such as broadcasting stock prices to update a price table, or triggering special application processing such as handling a failed transaction. User events can be used to send a message in a one-to-one or a one-to-many method.

Event subscription is established when the rtr_open_channel call is executed. See the RTR rtr_open_channel call description for details on this call. The rtr_open_channel call is as follows:


rtr_open_channel (channel, 
                  flags, 
                  facnam, 
                  rcpnam, 
                  pevtnum, 
                  access, 
                  numseg, 
                  pkeyseg) 

Two parameters on the call are used to establish event subscription: rcpnam and pevtnum.

rcpnam is a pointer to an optional channel name for receiving event messages. If a User Event is sent to a particular channel name, only those subscribers which match the name AND event number will be notified. For example, a client channel named "New York" and a client channel named "Hong Kong" could both subscribe to receive User Event number 999. If event 999 was triggered by the server using the channel named "Hong Kong," the event would be received only by the "Hong Kong" client. Specify RTR_NO_RCPNAM for this parameter if a name if not used. This parameter is case sensitive.

pevtnum is a pointer to lists of RTR and User event numbers to which the channel wants to subscribe. These lists use the numeric values of the events shown in the Table 2-5. Use the special symbols in Table 2-6 to construct the event list:

Table 2-6 Symbols for Event Lists
Symbol Description
RTR_NO_PEVTNUM No events selected.
RTR_EVTNUM_USERDEF Begin User Event list.
RTR_EVTNUM_RTRDEF Begin RTR Event list.
RTR_EVTNUM_ENDLIST End of entire list.
RTR_EVTNUM_UP_TO Specifies an event range in the form x RTR_EVTNUM_UP_TO y.
RTR_EVTNUM_USERBASE Smallest User Event number (0).
RTR_EVTNUM_USERMAX Largest User Event number (250).
RTR_EVTNUM_RTRBASE Smallest RTR Event number.
RTR_EVTNUM_RTRMAX Largest RTR Event number.

Example 2-3 illustrates how to set up a list of all User Event numbers for the rtr_open_channel call:

Example 2-3 User Event Example

rtr_evtnum_t all_user_events[]={ 
   RTR_EVTNUM_USERDEF, 
       RTR_EVTNUM_USERBASE, 
       RTR_EVTNUM_UP_TO, 
       RTR_EVTNUM_USERMAX, 
   RTR_EVTNUM_ENDLIST 
   } ; 

Example 2-4 illustrates how to set up a list of all RTR and User Event numbers for the rtr_open_channel call.

Example 2-4 RTR and User Event Example

rtr_evtnum_t all_events[]={ 
   RTR_EVTNUM_USERDEF, 
       RTR_EVTNUM_USERBASE, 
       RTR_EVTNUM_UP_TO, 
       RTR_EVTNUM_USERMAX, 
   RTR_EVTNUM_RTRDEF, 
       RTR_EVTNUM_RTRBASE, 
       RTR_EVTNUM_UP_TO, 
       RTR_EVTNUM_RTRMAX, 
   RTR_EVTNUM_ENDLIST 
   } ; 

Sending Events

A broadcast event is triggered when the rtr_broadcast_event call is executed. See the rtr_broadcast_event call description for details on this call. The rtr_broadcast_event call is as follows:


rtr_broadcast_event (channel, 
                     flags, 
                     pmsg, 
                     msglen, 
                     evtnum, 
                     rcpspc, 
                     msgfmt) 

The significant parameters on this call are:

Example 2-5 shows an rtr_broadcast_event call in use.

Example 2-5 Broadcast Event Example

if ( bServerShutdown ) 
{ 
sts = rtr_broadcast_event ( 
    /* channel */ BY_CHAN_CLIENT(cCurrentChannel,client)->chan, 
    /* flags   */ RTR_NO_FLAGS, 
    /* pmsg    */ &msgbuf, 
    /* msglen  */ cbTotalSize, 
    /* evtnum  */ USER_EVT_SHUTDOWN, 
    /* rcpnam  */ "*", 
    /* msgfmt  */ szMsgFmt); 
 
exit_if_error ( "rtr_broadcast_event", sts ); 
} 

Receiving Events

Any RTR transaction, RTR Event, or User Event can be received when the application executes the rtr_receive_message call. See the RTR rtr_receive_message call description for details on this call. The rtr_receive_message call is as follows:


rtr_receive_message (channel, 
                     flags, 
                     prcvchan, 
                     pmsg, 
                     maxlen, 
                     timoutms, 
                     pmsgsb) 

The significant parameters on this call are:

If the application has subscribed to events, any occurance of the call to rtr_receive_message could return an event notificacation. If an RTR Event notification is delivered, the rtr_receive_message call will return a message type rtr_mt_rtr_event, and the user buffer will contain the associated event message. If a User Event notification is delivered, the rtr_receive_message call will return a message type rtr_mt_user_event, and the user buffer will contain the associated user broadcast message.

Design consideration: When an RTR application executes an rtr_receive_message call, the programmer could incorrectly anticipate that a particular message type may be received and only write instructions to respond to the expected message. However, an RTR or User Event could be received on any instance of the rtr_receive_message call (as could other unanticipated RTR messages). Therefore, as a general application design guideline, the application developer should always program the application so that it can properly handle any type of message that could be received by the rtr_receive_message call.

Events are delivered in the order in which they are broadcast; therefore event serialization will be preserved for a particular user. However, RTR does not enforce any particular serialization across different subscribers, so different subscribers could receive event notifications in any order.

Example 2-6 shows an rtr_receive_message call in use.

Example 2-6 Receive Message Example

status = rtr_receive_message( &channel, 
                              RTR_NO_FLAGS, 
                              RTR_ANYCHAN, 
                              &receive_msg, 
 
                              RTR_ANYCHAN, 
                              &receive_msg, 
                              sizeof(receive_msg), 
                              receive_time_out, 
                              &msgsb); 
 
check_status( "rtr_receive_message", status ); 

2.11.3 Event Management by RTR

Event Routing

When an event subscription is created with the rtr_open_channel call, the event details are stored in a subscriber database on all routers. When an event is triggered, notification is delivered to all routers within that facility which are connected to that system. The routers then check their subscriber database for any systems which has subscribed to that event. If one or more subscribers are located, and the subscribers are currently attached to this router, then the router broadcasts the message to the subscribers. If no subscriber is located, then the message is discarded.

Event Delivery

RTR will reliably deliver RTR transactions and RTR events. The delivery of User Events on a properly configured system is reliable, however, delivery of User Events is subject to RTR Flow Control if the subscriber cannot process events as quickly as they are delivered. Flow Control is a message traffic governor which helps the effected system to manage a spike in message traffic. We will discuss in more detail the interaction of Flow Control and RTR event processing.

When a User Event is triggered, a broadcast including message data is routed to the subscriber system. User Events, along with RTR Events and transactions, are placed into an incoming message queue on the destination system until the subscriber application executes an rtr_receive_message call to receive the message into the application. If too many messages are sent to the destination system, then the RTR Flow Control feature will be activated.

Flow Control may then force the sending application to wait for a while in the next RTR call that sends data, or it may discard broadcasts from the message queue, until the message queue length reduces and Flow Control allows new broadcasts to be sent to the destination system. Because User Event broadcasts are usually used for streaming information such as the periodic update of a price table, RTR does not store event messages which are impacted by Flow Control for later processing. This technique would cause the application to spend time viewing stale data. Instead, RTR Flow Control may discard the message to help relieve the messaging backlog, and will rely on a future message delivery to supply the updated information.

Design issue: Because of the possibility that a User Event message could become delayed or discarded due to Flow Control, User Events should not be used for delivering information that is of a business critical nature including information that previously was, or later will be, used in a transaction. To compensate for the possibility of a discarded message, the application developer may consider adding a sequence number to the event message and providing a read-only transaction in the application to detect and request re- transmission of any discarded broadcast data from the sender.

Overhead of Using Events

Delivery of User Events is based upon the registration databases which are kept on the routers. The event is delivered from the sender to all connected routers, which means each event triggers a message traffic load of 1 (for a FE sender) or the number of routers (for a BE sender). The event is then propagated by the routers to all subscribers, creating message traffic of 0 or the number of systems with subscribers to the event.

Design Issue: Processing event messages does consume some system resources and could impact overall performance. If system resources become constrained, RTR flow control may activate which will reduce the RTR throughput on the affected systems. Care should be exercised to provide enough system resources to handle the message load.

2.11.4 Event Troubleshooting

Several RTR MONITOR screens can be helpful in troubleshooting events, as described below. Sample screens are available in the Reliable Transaction Router System Manager's Manual.

Monitoring Events

User Event traffic (broadcasts) may specifically be monitored for each node using the MONITOR BROADCAST screen in RTR. This screen shows the total event throughput, along with a count of any discarded broadcasts.

The MONITOR FACILITY screen in RTR provides a combined summary of all RTR Events and User Events processed for each facility.

The SHOW CLIENT/FULL and SHOW SERVER/FULL commands in RTR are helpful for viewing the current event subscription list for a particular client or server, along with any channel name specified in the rcpnam parameter on the rtr_open_channel call.

Execution of rtr_broadcast_event calls and event message traffic in RTR can be monitored using the MONITOR CALLS screen in RTR. This screen shows the frequency of use of the rtr_broadcast_event call, and the number of RTR Events and User Events processed. If an event is in pending ("pend") status, it indicates that the event is waiting for an rtr_receive_message call to be performed.

The MONITOR ROUTING screen shows the transaction and broadcast throughput on the system. This display shows the number of events and also the rate over time during the monitoring interval.

The MONITOR STALLS screen is helpful to determine if RTR Flow Control is affecting a particular system. Flow Control stalls that have occurred are categorized by duration. Any stall which lasts more than 60 seconds results in a Link Drop entry. A Stall ("stll") entry in the far-right column indicates that a Flow Control stall is currently in progress on the link indicated. For the purposes of User Event broadcast delivery, any stall could indicate that a broadcast message could have been discarded.

It is possible to monitor additional details of RTR Flow Control by using the MONITOR CONGEST, MONITOR FLOW, and MONITOR TRAFFIC monitor screens in RTR.

2.12 Nested Transactions

An RTR transaction can be included in a transaction that is coordinated by a parent transaction manager (TM). This is called a nested transaction or subtransaction. RTR, Microsoft DTC, Encina, Tuxedo, or another foreign transaction manager can act as the TM. In such cases the RTR transaction is termed a nested transaction (or subtransaction), with RTR acting as a Resource Manager (RM) for the parent transaction manager.

An RTR transaction can be joined to an existing transaction by a call to rtr_start_tx using the pjointxid argument.

By default, RTR treats a subtransaction as an intrinsic part of the transaction to which it was joined. This is equivalent to a scheme where the client directly involves all participating servers.

The joining transaction may not, however, be an intrinsic part of the joined transaction. That is, the server may have several alternatives for the subtransaction and only when all alternatives are exhausted will the joined transaction be aborted. In this case the server can specify the RTR_F_EXPENDABLE flag on the calls to rtr_send_to_server that are allowed to fail. If this flag is set and the subtransaction fails, RTR aborts the subtransaction as if it had never happened.

Table 2-7, Changes for Nested Transactions, lists changes made to RTR to effect use of nested transactions. One new call has been introduced and several have been changed.

Table 2-7 Changes for Nested Transactions
Change to: Description
rtr_open_channel RTR_F_OPE_FOREIGN_TM must be specified for a client channel to be used for nested transactions.
rtr_prepare_tx Lets the RTR client initiate the first (prepare) phase of the two-phase commit protocol for the nested transaction.
rtr_request_info Used for recovery processing.
rtr_set_info Used for recovery processing.
rtr_start_tx Must be called by the RTR client explicitly for nested transactions. This allows the Foreign Transaction Manager (FTM) transaction ID to be specified.
rtr_send_to_server The RTR_F_SEN_ACCEPT flag causes an implicit prepare of the transaction; that is, no additional call to rtr_prepare_tx is required.
RTR journal An RTR journal is required on a frontend node that is used for nested transactions.

2.13 Recovery for Foreign Transaction Managers

In the event of a failure of the application or the node where an RTR nested transaction is started, the foreign transaction manager must be able to determine which transactions are in an indeterminate state. The method for this is similar to the method traditionally used by RTR server applications to identify and deal with uncertain transactions.

When rtr_open_channel is called with RTR_F_OPE_FOREIGN_TM, a local journal scan is done (if not already done). Any transactions started by this foreign transaction manager that are in an incomplete state but in the correct facility are read into ACP memory. Before the rtr_mt_opened message is delivered to the application, the local journal scan and a local recovery of any transactions found in the journal is completed. That is, RTR will try to determine what was the final outcome of the transactions it has recovered from the journal.

After the rtr_mt_opened message has been delivered to the application, the application must ask RTR if there are any transactions in an incomplete state and tell RTR how to deal with them. This is known as the Foreign Transaction Manager (FTM) recovery phase. If the foreign transaction manager does not go through the recovery phase, then any incomplete transactions remain in the RTRACP on the frontend, and in the journal.

The application uses the rtr_request_info and rtr_set_info calls for foreign transaction manager recovery. Generally, the application calls rtr_request_info as follows:


status = rtr_request_info(...
          rtr_info_class_t = "ftx", 
          rtr_itemcode_t   = "$name",           /* Select item */ 
          rtr_selval_t     = "facility_name", 
          rtr_itemcode_t   = "kr_id,tx_id"      /* Get items */ 
          ...); 
 

This returns information about the transactions active on the frontend for the specific facility_name. The application then checks the key range ID (kr_id) value to see if it corresponds to the foreign transaction manager ID. If it does, the application can request further information about that transaction. For example:


  status = rtr_request_info(...
           rtr_info_class_t = "ftx", 
           rtr_itemcode_t   = "tx_id",   /* Select item */ 
           rtr_selval_t     = "tx id value from previous call", 
           rtr_itemcode_t   = "xid,state,jnl_state,sr_state,bloblen,blob" 
                                         /* Get items */ 
           ...); 

The journal state (jnl_state) field will have one of three values, and the action for the transaction depends on the value, as shown in Table 2-8:

Table 2-8 Nested Transaction Recovery
Journal State Description User Action
rtr_tx_jnl_prepare Transaction has been prepared.

Servers have voted on the transaction and are waiting for the final vote from the foreign transaction manager. The foreign transaction manager may have called rtr_accept_tx or rtr_reject_tx in a previous incarnation, but the failure occurred before the vote was received by the router or written to the frontend's journal.

rtr_set_info

Set the transaction state to either COMMIT or ABORT.

rtr_tx_jnl_commit Transaction has been committed.

Failure occurred after foreign transaction manager called rtr_accept_tx in a previous incarnation, and RTR unsure whether foreign transaction manager knows transaction outcome.

rtr_set_info

Continue with next operation.

rtr_tx_jnl_abort Transaction has been rejected.

Possibilities:

  1. Router has not received VREQ from the frontend (in ENQ state) or the transaction had been rejected by participant but ABORT has not reached the frontend.
  2. Router in VOTING state. Transaction timed out on router and aborted with COMSTAUNO.
rtr_set_info

Continue with next operation.

During the foreign transaction manager recovery phase, if needed, the application can get the user data that was passed in the pmsg parameter in the call to rtr_prepare_tx. The application gets this data by specifying the bloblen and blob item codes in the call to rtr_request_info (see above). The XID specified by the foreign transaction manager (rtr_xid_t) is also available using the same call.

Note that since the foreign transaction manager recovery phase uses rtr_request_info or rtr_set_info, this could be done in a separate thread or process. The only requirement is that the journal has been opened on the frontend (by a call to rtr_open_channel with RTR_F_OPE_FOREIGN_TM set). Foreign transaction manager recovery code could thus be kept in separate logic that is not directly associated with the rtr_open_channel call. Exactly how this is done depends on the foreign transaction manager architecture. An example of the use of rtr_set_info is presented in the section describing the rtr_set_info call.


Previous Next Contents Index