# hp Reliable Transaction Router
C Application Programmer's
Reference Manual

Previous | Contents | Index

            strcpy(keyvalue, "k");

with keyvalue passed as one of the bounds values, then potentially the bound value can differ from one open channel call to the next, because the two bytes following the "k" will contain uninitialized values but still form part of the key-bound definition. (In this case, one should clear the keyvalue buffer before copying the bounds values.)

A call to `rtr_open_channel()` may be used to create a named partition or to open a server channel associated with an existing named partition. To do this, supply a partition name when opening a server channel. The pkeyseg argument specifies an additional item of type `rtr_keyseg_t` , assigning the following values:

- `ks_type = rtr_keyseg_partition` , indicating that a partition name is being passed
- `ks_lo_bound` should point to the null-terminated string to use for the partition name

Note When using the RTR CLI, if a key-bound value length is less than the key length, the key bound is automatically null-padded to the required length. For example,
     RTR> call rtr_open_channel/server/type=string/low=1/high=2
Because no key length is specified, the length defaults to four. The low and high bound values are automatically null-padded to four bytes by RTR.

The key segment array may not contain more than `RTR_MAX_NUMSEG` elements.

XA Usage Specify `RTR_F_OPE_XA_MANAGED` only for a server channel. With this flag, use `ks_type = rtr_keyseg_rename` to indicate that the server application provides resource manager information when a channel is open. `ks_lo_bound` should point to the null-terminated string to use for the resource manager (RM) name, which cannot contain more than 31 letters. `ks_hi_bound` should point to the null-terminated string to use for the RM-specific open string used to connect to the underlying RM. The open string cannot contain more than 255 letters. Neither `ks_length` nor `ks_offset` apply when using the flag `RTR_F_OPE_XA_MANAGED` .

## Description

> The `rtr_open_channel()` call opens a channel for communication with other applications on a particular facility.

> The caller of `rtr_open_channel()` specifies the role (client or server) for which the channel is used.

> For use with XA:

> 1. Change the rtr_open_channel() call as described in the call description.
> 2. Remove unnecessary SQL calls from server code such as commit or rollback in a two-phase commit environment. If these calls remain in your application code, they may cause vendor-specific warnings.
> 3. RTR allows only one RM instance to be registered for each RTR partition.
> 4. Only one transaction is processed on an RTR channel at any given time. This implies that a server process or a thread of control can only open one channel to handle a single XA request.
> 5. Using a multithreaded server application is strongly recommended for better throughput.

Return Value A value indicating the status of the routine. Possible status values are:

RTR_STS_ACPNOTVIA | RTR ACP no longer a viable entity, restart RTR or application
RTR_STS_BYTLMNSUFF | Insufficient process quota bytlm, required 100000
RTR_STS_DTXOPENFAIL | Distributed transaction request to open a session to the RM has failed
RTR_STS_DUPLRMNAME | Duplicate RM partition name
RTR_STS_ERROPEJOU | Error opening journal file
RTR_STS_INSVIRMEM | Insufficient virtual memory
RTR_STS_INVACCESS | Invalid access argument
RTR_STS_INVCHANNEL | Invalid channel argument
RTR_STS_INVEVTNUM | Invalid evtnum argument
RTR_STS_INVFACNAM | Invalid facnam argument
RTR_STS_INVFLAGS | Invalid flags argument
RTR_STS_INVKSLENGTH | Invalid ks_length argument
RTR_STS_INVKSTYPE | Invalid ks_type argument
RTR_STS_INVNUMSEG | Invalid numseg argument
RTR_STS_INVPKEYSEG | Invalid pkeyseg argument
RTR_STS_INVRCPNAM | Invalid rcpnam argument
RTR_STS_INVRMNAME | Invalid resource manager name
RTR_STS_INVSVRCLIFLG | Either both /Client and /Server flags were supplied or they were missing
RTR_STS_JOUACCDEN | No access to journal for attempted operation: permission denied
RTR_STS_JOUNOTFOU | Journal not found
RTR_STS_MISSINGREQFLG | A required flag is missing
RTR_STS_NOACP | No RTRACP process available
RTR_STS_OK | Normal successful completion
RTR_STS_RMSTRINGLONG | Resource manager open or close string too long

##

### Examples

> Examples show the following:
> - A simple client application
> - A simple server application
> - An application using XA
> - An application using partition names

> Example 3-1 Client Application

>             rtr_channel_t channel;
>             rtr_status_t status;
>             rtr_string_t user_name;

>     /* Get the user's name through login or other user interface
>      */
>             user_name = <input data>

>     /* Open client application's channel to the router;
>      * use the facility named `CCardPurchases', and the user's
>      * name to identify this client.
>      *
>      * This client will receive messages only, no events,
>      * and is going to use a foreign transaction manager
>      * that implements the X/Open standard transaction
>      * formats.
>      */
>     status = rtr_open_channel(
>                         &channel,
>                         RTR_F_OPE_CLIENT | RTR_F_OPE_FOREIGN_TM,
>                         "CCardPurchases",
>                         user_name,
>                         RTR_NO_PEVTNUM,
>                         RTR_NO_ACCESS,
>                         RTR_NO_NUMSEG ,
>                         RTR_NO_PKEYSEG );

>             check_status(status);

> Example 3-2 Server Application

>     ***************************************************************************
>     /* Open a channel in a server application. This server will
>      * handle only records where the last name begins with A.
>      * It also wants an explicit message sent when it is time
>      * to prepare the transaction, and one when it is time to
>      * vote whether to accept or reject the transaction.
>      */
>     rtr_channel_t   channel;
>     rtr_status_t    status;
>     rtr_keyseg_t    p_keyseg[1];
>     rtr_string_t    last = "A";

>     /*
>      * Use this rtr_keyseg_t structure to define this server as
>      * handling only those records whose last name begins
>      * with `A'.
>      */
>     p_keyseg[0].ks_type = rtr_keyseg_string;
>     p_keyseg[0].ks_length  = 1;
>     p_keyseg[0].ks_offset  =  0;
>     p_keyseg[0].ks_lo_bound = last;
>     p_keyseg[0].ks_hi_bound = last;

>     /* Open the channel as a server that wants explicit ACCEPT and
>      * PREPARE messages. It is a member of the CcardPurchases
>      * facility, accepts no events (only messages) and we are
>      * sending 1 rtr_keyseg_t structure that defines those
>      * messages to be handled by this server.
>      *
>      * Note also that we are specifying that this channel
>      * will be `XA managed'; that is, the transaction manager
>      * will be one that implements the X/Open standard.
>      */
>     status = rtr_open_channel(
>                             &channel,
>         RTR_F_OPE_SERVER | RTR_F_OPE_EXPLICIT_ACCEPT |
>         RTR_F_OPE_EXPLICIT_PREPARE | RTR_OPE_XA_MANAGED,
>                       "CCardPurchases",
>                       NULL,
>                       RTR_NO_PEVTNUM,
>                       RTR_NO_ACCESS,
>                       1,
>                       p_keyseg);
>     check_status(status);

> Using RTR with XA

> The snippets from the sample server applications show use of the RM information, the XA flag, and commenting out RM commits and rollbacks.

> New XA example, for V4.1 and later

> Starting with RTR Version 4.1, when a server application opens a new channel it does not have to specify the `RTR_F_OPE_XA_MANAGED` flag and RM name along with the RM's attributes such as `open_string` in order to invoke RTR XA service. The server application just has to specify the name of a partition that is associated with a specific RM, provided that the user specifies an RM name when creating the partition. All transactions processed through this channel will be managed by the RTR XA service.

> Impact on Server Application

> Using an RTR XA service has some impact on existing server applications, as follows:

> - RTR will not present messages of type `mt_uncertain` to server applications. The server application does not have to replay transactions during the recovery. All transactions will be recovered by RTR when the facility is created.
> - The server application does not need to explicitly commit or roll back the transactions with the underlying resource manager because transactions are managed directly by RTR using the XA protocol.

> Example 3-3 shows how to open a new channel using RTR V4.1:

> Example 3-3 Sample XA Server Application, Version 4.1 and Later

>         srv_key[0].ks_type = rtr_keyseg_partition;
>             srv_key[0].ks_length = 0; /* N/A */
>             srv_key[0].ks_offset = 0; /* N/A */
>             srv_key[0].ks_lo_bound = &partition_name[0]; /* null terminated */

>           flag = RTR_F_OPE_SERVER |
>                  RTR_F_OPE_EXPLICIT_PREPARE |
>                  RTR_F_OPE_EXPLICIT_ACCEPT;

>           status = rtr_open_channel(&s_chan,
>                                   flag,
>                                   reply_msg.fac_name,
>                                   NULL,            /* rcpnam */
>                                   &pevtnum,
>                                   RTR_NO_ACCESS,
>                                   num_seg,         /* numseg */
>                                   srv_key);        /* key range */

> However, if the server application is running a version of RTR prior to RTR V4.0, the server application must specify the RTR_F_OPE_XA_MANAGED flag, the RM's name, and other RM attributes such as `open_string` . You must overload the `rtr_keyset_t` data structure with the RM-specific information and then pass it when creating an RTR channel, as shown in Example 3-4.

> Example 3-4 Sample XA Server Application Prior to Version 4.1

>                srv_key[0].ks_type = rtr_keyseg_unsigned;
>                 srv_key[0].ks_length = sizeof(rtr_uns_8_t);
>                 srv_key[0].ks_offset = 0;
>                 srv_key[0].ks_lo_bound = &low;
>                 srv_key[0].ks_hi_bound = &high;

>                 srv_key[1].ks_type = rtr_keyseg_rmname;
>                 srv_key[1].ks_length = 0; /* N/A */
>                 srv_key[1].ks_offset = 0; /* N/A */
>                 srv_key[1].ks_lo_bound = &rm_name[0];        /* null terminated */
>                 srv_key[1].ks_hi_bound = &xa_open_string[0]; /* null terminated */

>      flag = RTR_F_OPE_SERVER |
>                     RTR_F_OPE_EXPLICIT_PREPARE |
>                     RTR_F_OPE_EXPLICIT_ACCEPT |
>                     RTR_F_OPE_XA_MANAGED;

>                 status = rtr_open_channel(&s_chan,
>                                   flag,
>                                   reply_msg.fac_name,
>                                   NULL,            /* rcpnam */
>                                   &pevtnum,
>                                   RTR_NO_ACCESS,
>                                   num_seg,         /* numseg */
>                                   srv_key);        * key range */

> Example 3-5 Use of Partition Names

>     /*  Demonstrate use of partition names            */
>     /*                                                */
>     /*                                                */

>     #include    "rtr.h"
>     #include    <stdio.h>

>     main()
>     {

>     /* This program will open a server channel. Servers
>      * need to identify the partition they will be operating
>      * on by passing information coded in the pkeyseg argument.
>      * If the partition already exists and its name is known,
>      * it suffices to specify the partition name. If this is
>      * not the case, then the partition must be specified by
>      * describing the key segments. In the latter case, name
>      * information is optional. If present, the new partition
>      * will receive the specified name, otherwise a default
>      * name will be generated.                          */
>     /*                                                  */
>      * This program assumes the presence of a partition named
>      * par_test in the facility fac_test and opens a server
>      * channel to it. Create the partition prior to running
>      * the program, e.g.,                               */
>     /*                                                  */
>     /* RTR> create partition par_test/facility=fac_test */
>     /*                                                  */

>     rtr_channel_t    AChannel;
>     const char       *pszFacilityName    = "fac_test";
>     const char       *pszPartitionName   = "par_test";
>     rtr_status_t     status;
>     rtr_ope_flag_t   flags  = RTR_F_OPE_SERVER;
>     rtr_keyseg_t     partition_info;

>     partition_info.ks_type          = rtr_keyseg_partition;
>     partition_info.ks_lo_bound      = (rtr_pointer_t)pszPartitionName;
>     partition_info.ks_hi_bound      = NULL;
>                              /* Must be NULL             */

>     status  = rtr_open_channel(
>                               &AChannel,
>                               flags,
>                               pszFacilityName,
>                               RTR_NO_RCPNAM,
>                               RTR_NO_PEVTNUM,
>                               RTR_NO_ACCESS,
>                               1,
>                               &partition_info);

>     /* Call rtr_receive_message() to receive completion status    */
>     }

### See Also

> `rtr_close_channel()`

# rtr_receive_message

> Receive a message from RTR or the application.

## Syntax

> status = rtr_receive_message (pchannel, flags, prcvchan, pmsg, maxlen, timoutms, pmsgsb)

> Argument | Data Type | Access
> --- | --- | ---
> status | rtr_status_t | write
> pchannel | rtr_channel_t | write
> flags | rtr_rcv_flag_t | read
> prcvchan | rtr_channel_t | read
> pmsg | rtr_msgbuf_t | write
> maxlen | rtr_msglen_t | read
> timoutms | rtr_timout_t | read
> pmsgsb | rtr_msgsb_t | write

## C Binding

> rtr_status_t rtr_receive_message (

> rtr_channel_t *pchannel ,
> rtr_rcv_flag_t flags ,
> rtr_channel_t *prcvchan ,
> rtr_msgbuf_t pmsg ,
> rtr_msglen_t maxlen ,
> rtr_timout_t timoutms ,
> rtr_msgsb_t *pmsgsb
> )

## Arguments

> ### pchannel

> The channel identifier on which the message was received.

> ### flags

> No flags are currently defined. Specify `RTR_NO_FLAGS` for this parameter.

> ### prcvchan

> A pointer to a list of channels on which a receive is required. This parameter can be used to select a subset of channels on which messages can be received. Terminate the list with `RTR_CHAN_ENDLIST` .

> If no selection is required, that is, a receive from any open channel is acceptable, specify `RTR_ANYCHAN` for this parameter.

> ### pmsg

> Required pointer to the user buffer where the received message is written.

> ### maxlen

> Size allocated in the user buffer for received messages, in bytes.

> ### timoutms

> Receive timeout specified in milliseconds. If the timeout expires, the call completes with status RTR_STS_TIMOUT.

> If no timeout is required, specify `RTR_NO_TIMOUTMS` .

> ### pmsgsb

> Pointer to a message status block describing the received message. The message status block is shown in Example 3-6.

> Example 3-6 RTR Message Status Block

>     typedef struct          /* RTR message status block */
>     {
>         rtr_msg_type_t msgtype;
>         rtr_usrhdl_t usrhdl;
>         rtr_msglen_t msglen;
>         rtr_tid_t  tid;
>         rtr_evtnum_t evtnum;
>     } rtr_msgsb_t ;

> The msgtype field can assume one of the values listed in Table 2-2, RTR Received Message Types for Server Applications and Table 2-3, RTR Received Message Types for Client Applications.

> The usrhdl field contains the value supplied with a call to `rtr_set_user_handle()` .

> The msglen field contains the length of the data stored in the user buffer after the call has been executed.

> The tid field contains the RTR unique ID for the transaction to which this received message belongs.

> The evtnum field contains the event number if the msgtype field is `rtr_mt_rtr_event` or `rtr_mt_user_event`.

## Description

> The `rtr_receive_message()` call is used to receive a message.

> The caller must have previously opened at least one channel (via `rtr_open_channel()` or `rtr_request_info()` ).

> By default, this function waits for a message to become available if no message is currently ready to be received.

> Upon successful return (RTR_STS_OK), the message status block pointed to by pmsgsb contains the description of the message received.

> When a client application calls `rtr_send_to_server` , RTR sends the message from frontend to router. It is the router's job to find out which key range the message belongs to (by looking at the key field in the application message), and then to forward the message to the backend node where the server application for this key range is running. If the router does not know of a backend that has a server running for this key range, then the router aborts the transaction. In this case, the client application receives an `rtr_mt_rejected` message for this transaction with status RTR_STS_NODSTFND.

> If a client application receives an RTR_STS_NODSTFND error, then the client can try to resend the transaction, as the cause may have been only temporary. Note that the reasons the router cannot find a backend node with an appropriate server include:

> 1. The application server for this key range has not been started.
> 2. The link between the router and backend has gone down.
> 3. In unusual circumstances, a transaction can be rejected with RTR_STS_NODSTFND status after the client calls `rtr_accept_tx` . This can occur for transactions with multiple participants and no timeout specified where the link between the router (which is quorate) and one of the backend participants has gone down for a period greater than the router's transaction replay timeout period. (This can occur even if the messages in the transaction had all been sent with the `RTR_F_SEN_EXPENDABLE` flag set.)

Return Value A value indicating the status of the routine. Possible status values are:

RTR_STS_ACPNOTVIA | RTR ACP no longer a viable entity, restart RTR or application
RTR_STS_BYTLMNSUFF | Insufficient process quota bytlm, required 100000
RTR_STS_INVCHANNEL | Invalid channel argument
RTR_STS_INVFLAGS | Invalid flags argument
RTR_STS_INVMSG | Invalid pmsg argument
RTR_STS_INVRMNAME | Invalid resource manager name
RTR_STS_NOACP | No RTRACP process available
RTR_STS_NOXACHAN | No XA channel available
RTR_STS_OK | Normal successful completion
RTR_STS_SRVDCLSBY | Successful server declaration, but as standby
RTR_STS_TIMOUT | Call to rtr_receive_message timed out
RTR_STS_TRUNCATED | Buffer too short for msg Message has been truncated

## Example

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

>             check_status( "rtr_receive_message", status );

>     /* The rtr_msgsb_t tells us what type of
>      * message we are receiving. This server has asked to
>      * be notified when it is time to prepare the transaction.
>      * It should also handle other message types, as well.
>      */
>             if (msgsb.msgtype == rtr_mt_prepare)
>             {
>                     // Do the work necessary to prepare the transaction
>                     // before committing.

### See Also

> `rtr_broadcast_event()`
> `rtr_accept_tx()`
> `rtr_open_channel()`
> `rtr_reject_tx()`
> `rtr_send_to_server()`

Previous | Next | Contents | Index