Previous | Contents | Index |
To use broadcast messaging with the C++ API, client and server applications can overload their event handlers.
To enable communication between two applications of the same type, create a second transaction controller of the other type. Messaging destination names can include wildcards, enabling flexible definition of the subset of recipients for a particular broadcast.
Use the SendApplicationEvent method to broadcast a user-event message. Broadcast types include user events and RTR events; both are numbered and can be named.
A user broadcast is named or unnamed. An unnamed broadcast performs a match on the user event number; the event number completely describes the event. A named broadcast performs a match on both user event number and recipient name. The recipient name is a user-defined string. Named broadcasts provide greater control over who receives a particular broadcast.
Named events specify an event number and a textual recipient name. The name can include wildcards (% and *).
For all unnamed events, specify the evtnum field and RTR_NO_RCPSPC as the recipient name.
For example, the following code specifies named events for all subscribers:
SendApplicationEvent( evUserEventNumber, "*", RTR_NO_MSGFMT)
For a broadcast to be received by an application, the recipient name specified by the subscribing application on its RegisterFacility method for clients and RegisterPartition method for servers must match the recipient specifier used by the broadcast sender on the SendApplicationEvent call.
RTR_NO_RCPSPC is not the same as "*". |
An application receives broadcasts with the Receive method. A message type returned in the RTRData buffers informs the application of the type of broadcast received. For example,
Receive(...pmsg,maxlen,...pmsgsb);
The user event would be in msgsb.msgtype == rtr_mt_user_event . User broadcasts can also contain a broadcast message. This message is returned in the message buffer provided by the application. The size of the user's buffer is determined by the maxlen field. The number of bytes actually received is returned by RTR in the msglen field of the message status block.
RTR delivers status information to which client and server applications can subscribe. Status information is delivered as messages, where the type of each message is an RTR event.
RTR events are numbered. The base value for RTR events is defined by the symbol RTR_EVTNUM_RTRBASE ; its maximum value is defined by the symbol RTR_EVTNUM_RTRMAX . RTR events and event numbers are listed in the Programming with the C++ API chapter of this guide and in the RTR header file rtrapi.h .
An application can subscribe to RTR events to receive notification of external events that are of interest to the application. For example, a shadow server may need to know if it is a primary or a secondary server to perform certain work, such as uploading information to a central database, that is done at only one site.
To subscribe to all RTR events, use the range indicators RTR_EVTNUM_RTRBASE and RTR_EVTNUM_RTRMAX .
RTR events are delivered as messages of type rtr_mt.rtr.event . Read the message type to determine what RTR has delivered. For example,
rtr_status_t Receive( *pRTRData )
The event number, evtnum, is returned in the RTRData. The following RTR events return key range data back to the client application:
In application design, you may wish to consider creating separate facilities for sending broadcasts. By separating broadcast notification from transactional traffic, performance improvements can be substantial. Facilities can further be reconfigured to place the RTR routers strategically to minimize wide-area traffic.
A server application can expect to see a primary or secondary event delivered only in certain transaction states. For more detail, see the state diagrams in Appendix C, Server States.
RTR callout servers enable security checks to be carried out on all requests using a facility. Callout servers can run on backend or router nodes. They receive a copy of every transaction delivered to or passing through the node, and they vote on every transaction. To enable a callout server, use the /CALLOUT qualifier when issuing the RTR CREATE FACILITY command. Callout servers are facility based, not key-range or partition based.
An application enables a callout server with the CreateFacility method in the RTRFacilityManager class. For a router callout, the application sets the EnableRouterCallout boolean to true:
RTRFacilityManager.CreateFacility(... bEnableRouterCallout = true ...); |
For a backend callout server, the application sets the EnableBackendCallout boolean to true:
RTRFacilityManager.CreateFacility(... bEnableBackendCallout = true); |
RTR provides a C application programming interface (API) that features transaction semantics and intelligent routing in the client/server environment. It provides software fault tolerance using shadow servers, standby servers, and concurrent server processing. It can provide authentication with callout servers. RTR makes single-point failures transparent to the application, guaranteeing that, within the limits of reliability of the basic infrastructure and the physical hardware used, a transaction will arrive at its destination.
The RTR C API contains 16 calls that address four groups of activity:
The initialization call signals RTR that a client or server application wants to use RTR services and the termination call releases the connection once the requested work is done.
Messaging calls enable client and server applications to send and receive messages and broadcasts.
Transactional calls collect groups of messages as transactions (txn).
Informational calls enable an application to set RTR options or interrogate RTR data structures.
Initiation/termination Calls | Messaging Calls | Transactional Calls | Informational Calls | Manipulation |
---|---|---|---|---|
rtr_open_channel | rtr_broadcast_event | rtr_start_tx | rtr_request_info | rtr_set_info |
rtr_close_channel | rtr_reply_to_client | rtr_accept_tx | rtr_get_tid (tid is the transaction identifier) | rtr_set_user_ handle |
rtr_send_to_server | rtr_reject_tx | rtr_error_text | rtr_set_wakeup | |
rtr_receive_message | rtr_prepare_tx |
To execute these calls using the RTR CLI, precede each with the keyword CALL. For example,
RTR> CALL RTR_OPEN_CHANNEL |
Table 5-2 provides additional information on RTR API calls, which are listed in alphabetical order.
Routine Name | Description | Client and Server | Client Only | Server Only | Returns completion status as a message |
---|---|---|---|---|---|
rtr_accept_tx() | Votes on a transaction (server). | Yes | Yes | ||
Commits a transaction (client). | Yes | ||||
rtr_broadcast_event() | Broadcasts an event message. | Yes | |||
rtr_close_channel() | Closes a previously opened channel. | Yes | |||
rtr_error_text() | Converts RTR message numbers to message text | Yes | |||
rtr_get_tid() | Gets the current transaction ID. | Yes | |||
rtr_open_channel() | Opens a channel for sending and receiving messages. | Yes | Yes | ||
rtr_prepare_tx() | Prepares a nested transaction to be committed. | Yes | Yes | ||
rtr_receive_message() | Receives the next message (transaction message, event or completion status); returns a message and a message status block. | Yes | |||
rtr_reject_tx() | Rejects a transaction. | Yes | |||
rtr_reply_to_client() | Sends a response from a server to a client. | Yes | |||
rtr_request_info() | Requests information from RTR. | Yes | Yes | ||
rtr_send_to_server() | Sends a message from a client to the server(s). | Yes | |||
rtr_set_info() | Sets an RTR parameter. | Yes | Yes | ||
rtr_set_user_handle() | Associates a user value with a transaction. | Yes | |||
rtr_set_wakeup() | Sets a function to be called on message arrival. | Yes | |||
rtr_start_tx() | Explicitly starts a transaction and specifies its characteristics. | Yes |
The rtr.h file included with the product defines all RTR data, status, and message types, including text that can be returned in error messages from an application. You must use it in application compilation.
To support the multi-operating system environment, error codes are processed by RTR using data values in rtr.h , and translated into text messages. Status codes are described in the Reliable Transaction Router C Application Programmer's Reference Manual.
The command line interface (CLI) to the RTR API enables the programmer to write short RTR applications from the RTR command line. This can be useful for testing short program segments and exploring how RTR works. For an example of a sequence of commands that starts RTR and exchanges messages between a client and a server, see RTR Getting Started.
The design of an RTR client/server application should capitalize on the RTR multi-layer model, separating client activity in the application from server and database activity. The RTR client software layer passes messages transparently to the router layer, and the router layer sends messages and transactions reliably and transparently, based on message content, to appropriate server processes. Server application software typically interacts with database software to update and query the database, and respond back to the client.
All RTR calls complete synchronously. Subsequent completion events are returned as messages to the application (see Table 5-2).
The client/server environment has both plusses and minuses. Performing processing on the client that does not need to be handled by the server is a plus, as it enables the client to perform tasks that the server need have no knowledge of, and need expend no resources to support. With RTR as the medium for moving transactions from client to server, the application need not be concerned in detail about how the transactions are sent, or what to do in the event of node or site failures. RTR handles all required journaling and recovery without direct intervention by the application. The application needs no code to deal with server and link failures. However, the application must deal with transactions that get aborted, such as business-logic cases (for example, insufficient funds in a bank account) where rules dictate the abort. Table 5-3 lists the types of transaction aborts.
Transaction Aborted | Action |
---|---|
Business logic cases. For example, insufficient funds in a bank account. | Application reports error to user. Server or client aborts transactions. |
RTR generated abort, RTR_STS_NODSTFND . RTR has exhausted all redundancy paths. | Application reports system unavailable, perhaps temporarily. |
Timeout abort. | Task dependent. Try again or inform user. |
Deadlock aborts. | None. RTR reschedules. |
In a client/server environment, application design becomes more complex because the designer must consider what tasks the clients are to perform, and what the servers must do. Typically the client application will capture information entered by the user, while the server interacts with the database to update the database with transactions passed to it by the router.
The RTR journal is always in use, recording transaction activity to persistent storage. The journal thus provides the capability of recovery from any single hardware or process failure. When a server application no longer provides service, for example, when it goes off line, goes down, or is taken out of service temporarily, RTR aborts all transactions for that service with RTR_STS_NODSTFND . When doing transactional shadowing, the journal at the active site is used to record transactions, for the out-of- service site. Journaling on frontends is required to support nested transactions to record the final state of a transaction.
If transactions do not update the database, specify them as read-only by using the RTR_F_SEN_READONLY flag on the rtr_send_to_server call. Read-only transactions are not recovered as uncertain transactions. Also, in a shadowed environment, these transactions would not be remembered and would therefore save on journal space.
Client applications use data content routing to route each transactional request to the appropriate server servicing the correct database segment. The key value supplied by the client application in the key fields (as defined in the definition of the partition) is used by RTR to achieve data content or data partition routing.
RTR enables an application to route transactions by partition or key range , rather than sending all transaction requests to a single server application.
When RTR has chosen a specific server for a request within a given transaction, RTR ensures that all requests within that transaction are routed to the same server application channel.
Key ranges, or data partitions, are a major concept in RTR. An application is said to service a partition. Failovers and other availability attributes are applied to all applications, which service a given partition. All server applications able to service a specific data partition on a given node are called concurrents of one another. Concurrent servers may be either multiple channels within a given process, or separate processes.
Partitions can be given names. This lets the system manager manipulate the attributes for a partition at runtime. For example, the operator can temporarily suspend the presentation of online transactions to the partition. This provides time to initiate a database backup operation.
Partitions, in RTR, are the essence of routing. The server application declares its intention to service a certain partition or key range by associating itself with a name, or explicitly defining the key format and range of values.
A partition has many attributes, some of which are specified by the programmer or operator. Some key attributes include:
To plan for future expansion, consider using compound keys rather than single field keys. For example, using a bank example, with a bank that has multiple branches, an application that routes data to each bank can use a BankID key field or partition. Over time, the application may also need to further subdivide transactions not only by bank but also by customer ID. If the application is initially written with a compound key providing both a BankID and a CustomerID key, it can be simpler to make such a change in future.
An application can be multithreaded. There are several ways to use multithreading in the application architecture. Check the Reliable Transaction Router Release Notes and SPD for the current extent of support for multithreaded programming for a given platform.
The two common ways of using multithreading are:
One word of caution for application developers who intend to deploy on OpenVMS: AST programming and threading do not mix well, and may cause intermittent deadlocks. It is therefore prudent not to use ASTs when using threads on OpenVMS with RTR.
For a client, an application typically uses the following calls in this order:
rtr_open_channel()
rtr_receive_message() |
one per channel |
rtr_start_tx()
rtr_send_to_server() [one or more, zero or more receive messages for the expected number of replies] rtr_accept_tx() rtr_receive_message() |
per transaction |
For a server, an application typically uses the following calls in this order:
rtr_open_channel()
rtr_receive_message() |
one per channel |
rtr_receive_message() [one or more]
rtr_reply_to_client() [zero or more] rtr_accept_tx() rtr_receive_message() |
per transaction |
The rtr_receive_message call returns a message and a message status block ( MsgStatusBlock ). For example,
... status = rtr_receive_message(&Channel, RTR_NO_FLAGS, RTR_ANYCHAN, MsgBuffer, DataLen, RTR_NO_TIMOUTMS, &MsgStatusBlock); |
The message status block contains the message type, the user handle, if any, the message length, the TID, and the event number, if the message type is rtr_mt_rtr_event or rtr_mt_user_event . For more information on the message status block, see the descriptions of rtr_receive_message and rtr_set_user_handle in the Reliable Transaction Router C Application Programmer's Reference Manual.
Previous | Next | Contents | Index |