Previous | Contents | Index |
The following pseudocode examples of a client and a server application
illustrate the use of the C programming API. Details have been omitted
to keep the basic structure clear.
2.5.1 Simple Client
This simple client program issues transactions and receives event messages. It simply issues one transaction, waits for it to be processed, and in the meantime handles any events that arrive. It then issues the next transaction. It does not need to wait until one transaction finishes before starting the next.
The following two examples are single-threaded. They can be made multithreaded by opening more channels. The structure of the main receive loop does not need to be changed to implement this. Note that rtr_receive_message receives the next message in the process input queue for any of the channels opened by the program (unless preferred channels have been requested in the rtr_receive_message ).
Example 2-1 Example Client |
---|
rtr_open_channel() ! Open a channel to the required facility rtr_receive_message() ! Get the completion status of the open call ! success returns rtr_mt_opened send_loop: rtr_send_to_server( ...RTR_F_SEN_ACCEPT....) ! Send a tx-message and ! implicitly start a new tx rcv_loop: rtr_receive_message() ! Find out what RTR wants to tell us next switch (message_received_type) { case rtr_mt_reply: Process_Reply_from_Server; break; case rtr_mt_rtr_event: Process_RTR_Event; break; case rtr_mt_user_event: Process_User_Event; break; case rtr_mt_accepted: Tell_User_It_Worked; break; case rtr_mt_rejected: Tell_User_About_Failure; break; } IF ( message_received_type = rtr_mt_accepted ) OR ( message_received_type = rtr_mt_rejected ) THEN GOTO send_loop ! Last transaction done, issue the next one ELSE GOTO rcv_loop ! Get the next incoming message |
In Example 2-1, note that the switch statement tests on message type.
All messages that are received from RTR have a
message type; for further information, see Section 2.11.
2.5.2 Simple Server
Example 2-2 is a simple server that receives transactions and events.
Example 2-2 Example Server |
---|
rtr_open_channel() ! open a channel to the desired facility rtr_receive_message() ! get the completion status of the open call ! success returns rtr_mt_opened rcv_loop: rtr_receive_message() ! Find out what RTR wants to tell us next CASE message_received_type OF rtr_mt_msg1: Do_Some_SQL_And_Maybe_Send_A_Reply; rtr_mt_msgn: Do_Some_More_SQL_And_Maybe_Send_A_Reply; rtr_mt_prepare: Accept_or_Reject_Tx ; rtr_mt_rtr_event: Process_RTR_Event; rtr_mt_user_event: Process_User_Event; rtr_mt_accepted: Commit_DB ; rtr_mt_rejected: Rollback_DB ; END_CASE; GOTO rcv_loop |
As can be seen from the examples in the previous section, an application first opens one or more channels by calling rtr_open_channel .
The application can then process transactions and events on the channels it has opened. When a channel is no longer needed, the application closes it by calling rtr_close_channel .
A transaction becomes associated with a channel in one of the following circumstances:
From this point on the channel remains associated with the transaction until one of the following occurs:
Note that RTR considers a transaction to have been committed to the database (so that it does not need to replay it in case of failure) when the server indicates willingness to receive a new transaction by calling rtr_receive_message on the channel, after having received the transaction completion status.
Calling
rtr_close_channel
also indicates to RTR that the
last transaction has been committed.
2.7 Concurrency
The routine rtr_receive_message is used by an application to receive all incoming messages, responses and events. This provides a single consistent method of information delivery.
All RTR routines other than rtr_receive_message complete immediately, and any responses are queued for later reception by rtr_receive_message .
The application calling rtr_receive_message may choose whether (and how long) it should wait for an incoming message to arrive (if there is no message available for immediate reception).
In addition, the application may optionally specify a "wakeup
routine" to be called by RTR when a message becomes available for
reception.
2.8 Exit Handlers in Applications
Making RTR calls from within an application exit handler does not work, because the channel is usually closed by the time the application exits. If an exit handler contains a call to RTR, then the exit handler must be declared after the first call to RTR. If an exit handler is declared before the first call to RTR, then any call to RTR made within the exit handler will return an error.
The error status returned is
RTR_STS_INV_CHANNEL
.
2.9 Using the RTR Set Wakeup Routine
An application program may typically wish to respond to input from more than one source. An example of this is an application program that prompts for user input in a window and at the same time displays information received asynchronously via broadcast events.
To avoid the application polling its various input sources, RTR provides the rtr_set_wakeup routine. This allows the application to specify a routine to be called when there is data to be received from RTR. The application program can then be coded as shown in the example provided with the rtr_set_wakeup routine.
The processing context of the application wakeup handler depends upon the platform and RTR library variant employed.
Core RTR functionality and the C API are delivered in a single sharable library. This library is named rtrdll on Windows, and librtr on other platforms. The latter is supplied in two variants: librtr_r which is targeted at developers of threaded applications, and librtr which provides a platform-specific wakeup handler implementation.
Wakeup handlers under rtrdll and librtr_r are called in a dedicated thread created by RTR for this purpose.
Wakeup handlers under librtr on UNIX are called from a signal handler established by RTR to handle SIGIO. If the application also wishes to use this signal, it should establish its handler prior to the first call to the RTR API. In this case the signal handler should be aware that the SIGIO signal may have been generated by RTR, not necessarily by the event for which the signal handler was written.
Wakeup handlers under librtr on OpenVMS are called from an AST handler. In the presence of multiple competing ASTs, calling rtr_set_wakeup() from the wakeup handler can be used to limit RTR processing and serialize the execution of RTR events with other asynchronous activity in the program.
Rtrdll and librtr_r provide thread synchronization and are safe to use in a multithreaded environment. Librtr offers no such protection.
It is not anticipated that applications on OpenVMS will want to use both threads and ASTs. For this reason the RTR V2 API is functional in librtr on OpenVMS only.
Summarizing:
Sharable Name | Thread-safe | Wakeup Mechanism | V2 API |
---|---|---|---|
rtrdll | Yes | RTR thread | No |
librtr_r | Yes | RTR thread | No |
librtr /UNIX | No | signal handler | No |
librtr /OpenVMS | No | AST | Yes |
The wakeup handler itself cannot call any function that might have to wait such as rtr_reply_to_client , rtr_send_to_server or rtr_broadcast_event ; the only RTR call allowed in the wakeup handler is rtr_receive_message called with a zero timeout. Other RTR calls may block or halt processing when they need transaction IDs or flow control, which will cause unexpected behavior. This restriction applies to both threaded and unthreaded applications.
A threaded application does not need to use a wakeup handler; its functionality can be provided by a dedicated thread that receives and dispatches RTR messages.
Functions permitted in an rtr_set_wakeup() handler:
Reliable Transaction Router provides client and server optimizations for greater
performance and programming ease.
2.10.1 Client Optimization
Reliable Transaction Router introduces greater flexibility and efficiency in how transactions are packaged at the client.
The total sequence of events that a client application has to execute are as follows:
In Reliable Transaction Router, all these steps can be followed if required, but optimizations allow some of the steps to be handled implicitly.
Reliable Transaction Router introduces greater flexibility and efficiency in how transaction voting (acceptance by servers) is handled; RTR allows implicit voting.
In detail, the sequence of events that a server executes is as follows:
This scheme is not efficient in some cases. For example, a callout (authentication) server may only need to receive the first message of a multiple message transaction, whereupon it can vote immediately.
In Reliable Transaction Router, all these steps can be enforced if required, but optimizations allow some of the steps to be handled implicitly.
An implicit accept allows Step 3 to be omitted; the transaction is accepted by the server when it does the next call to rtr_receive_message .
These optimizations are controlled by flags (
RTR_F_OPE_EXPLICIT_PREPARE
and
RTR_F_OPE_EXPLICIT_ACCEPT
)
on the call used to open a server channel.
2.10.2.1 The RTR_F_OPE_EXPLICIT_PREPARE Flag
A server channel may be opened with the RTR_F_OPE_EXPLICIT_PREPARE flag; this specifies that it will receive prepare messages (messages of type rtr_mt_prepare ). The server is then expected to accept or reject a transaction on receipt of this message (or earlier). The server may accept the transaction before the prepare message is sent: in this case, the prepare message is not delivered to the server.
The default behaviour of RTR (for example, when this flag is
not set in the call to
rtr_open_channel
) is to not send
prepare messages to the server application. In this case, RTR expects
the server to accept or reject transactions without RTR triggering it
into voting activity by sending prepare messages.
2.10.2.2 The RTR_F_OPE_EXPLICIT_ACCEPT Flag
A server channel may be opened with the RTR_F_OPE_EXPLICIT_ACCEPT flag; this specifies that it will accept transactions only by making an explicit call to rtr_accept_tx .
The default behaviour of RTR (that is, when this flag is not set) is to treat a server's call to rtr_receive_message (after the last transaction message has been received) as an implicit acceptance of the transaction.
If a transaction has been accepted before the last message has been received, the setting of the RTR_F_OPE_EXPLICIT_ACCEPT is irrelevant.
However, if a transaction has not been prematurely accepted, when the server's vote is required by RTR, the setting of the flags have the following effects:
All RTR calls return a completion status immediately except rtr_receive_message . If the immediate status is successful, many calls will also result in a further message or messages being delivered on the channel.
All RTR received messages are of a defined message type. The message type is given in the message status block. (See pmsgsb on rtr_receive_message in Chapter 3).
The message type allows your application to handle the message appropriately; the message type indicates whether this message contains information that is part of a transaction, or a broadcast, or RTR informational, and so on.
The use of rtr_receive_message for both RTR status messages and application data messages requires the application designer to consider how to respond to the different message types. Message types for server and client applications are listed in Table 2-2 and Table 2-3.
All received messages cause the message status block (pmsgsb on rtr_receive_message ) to be filled; most message types also put data into the user buffer (pmsg on rtr_receive_message ). Only the rtr_mt_prepare message type does not fill the user buffer.
Table 2-4 provides information put in the user buffer for each message type. Table 2-2 and Table 2-3 list all the message types that server channels or client channels can receive, together with a description of their meaning and the recommended application behavior. Order is alphabetical.
Message Type | Description | Recommended Action |
---|---|---|
rtr_mt_accepted | The specified transaction has been accepted by all participants. | Commit the transaction in the database and release database locks. |
rtr_mt_closed | Channel has been closed. Sent by RTR if an rtr_open_channel fails (that is, no such facility) or as a result of an operator command such as DELETE FACILITY, or the last message from a rtr_request_info or rtr_set_info call. | Examine reason status. Roll back database for any active transaction. |
rtr_mt_msg1 | This is the first application message of a transaction, sent by a client. | Process the message. |
rtr_mt_msg1_uncertain | This is the first application message of a replayed transaction, that is, a previous incarnation of the server failed during the voting phase. | Check in database to see if the transaction has been processed. If not processed, redo the transaction; else forget the transaction. |
rtr_mt_msgn | This is the nth application message (that is, not the first) of a transaction, sent by a client. | Process the message. |
rtr_mt_opened | Channel has been opened. | Use the channel. |
rtr_mt_prepare | The specified transaction is complete (that is, all messages from the client have been received). This message type is only received by a server that specified that it requires a prepare. (Servers specify this by using the RTR_F_OPE_EXPLICIT_PREPARE flag on the rtr_open_channel call.) | Call either rtr_reject_tx to reject the transaction, or have all required database records locked before calling rtr_accept_tx to accept the transaction. |
rtr_mt_rejected | The specified transaction has been rejected by a participant. | Roll back the transaction. |
rtr_mt_request_info | Message from a previous call to rtr_request_info . | Use information as required. |
rtr_mt_rtr_event | An RTR event with an associated message. | evtnum describes which RTR event occurred. See Table 2-5. |
rtr_mt_set_info | Message from a previous call to rtr_set_info . | Use information as required. |
rtr_mt_user_event | A user event with an associated message. | evtnum has an application-specific meaning. |
Message Type | Description | Recommended Action |
---|---|---|
rtr_mt_accepted | The specified transaction has been accepted by all participants. | Inform user of successful completion. |
rtr_mt_closed | Channel has been closed. Sent by RTR if an rtr_open_channel fails (for example, no such facility) or as a result of an operator command such as DELETE FACILITY, or the last message from an rtr_request_info or rtr_set_info call. | Examine reason status. |
rtr_mt_opened | Channel has been opened. | Use the channel. |
rtr_mt_rejected | The specified transaction has been rejected by a participant. | Inform user of reason for failure. |
rtr_mt_reply | This is an application reply message sent by a server. | Process message. |
rtr_mt_request_info | Message from a previous call to rtr_request_info . | Use information as required. |
rtr_mt_rettosend | This message (which had been sent with the RTR_F_SEN_RETURN_TO_SENDER flag) could not be delivered and has been returned. | Take appropriate action for the transaction as required by your application. |
rtr_mt_rtr_event | An RTR event with an associated message. | evtnum describes which RTR event occurred. See Table 2-5. |
rtr_mt_set_info | Message from a previous call to rtr_set_info . | Use information as required. |
rtr_mt_user_event | A user event with an associated message. | evtnum has an application-specific meaning. |
Message Type | Buffer Contents |
---|---|
rtr_mt_accepted | rtr_status_data_t , see Example 2-3. |
rtr_mt_closed | rtr_status_data_t , see Example 2-3. |
rtr_mt_msg1 | The first application message of a transaction, sent by a client. |
rtr_mt_msg1_uncertain | The first application message of a replayed transaction. |
rtr_mt_msgn | The nth application message (that is, not the first) of a transaction, sent by a client. |
rtr_mt_opened | rtr_status_data_t , see Example 2-3. |
rtr_mt_prepare | None. |
rtr_mt_rejected | rtr_status_data_t , see Example 2-3. |
rtr_mt_reply | An application reply message sent by a server. |
rtr_mt_request_info | Requested information from rtr_request_info . |
rtr_mt_rettosend | Returned message. |
rtr_mt_rtr_event | RTR event message. |
rtr_mt_set_info | Set information from rtr_set_info . |
rtr_mt_user_event | The user broadcast message. |
Previous | Next | Contents | Index |