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:

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:

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:

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