Reliable Transaction Router
Application Programmer's Reference Manual


Previous Contents Index

The pkeyseg parameter is not required for client channels or callout server channels. (Callout servers always receive all messages.) Specify RTR_NO_PKEYSEG when defining client channels. The ks_type field can be one of the data types shown in Table 3-7.

If an rtr_keyseg_t of rtr_keyseg_string is specified, then it is up to the application programmer to ensure that the key value is valid for the complete range of the key length. For example, if the key length is 4, and server code includes a statement like:


        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, since 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 


Since 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.

Nested Transaction Usage

When the RTR_F_OPE_FOREIGN_TM flag is specified, then a transaction manager (TM) identifier can also be passed as a parameter. The pkeyseg parameter is used for this purpose (analogous to its use when RTR_F_OPE_XA_MANAGED is specified, for example). If the pkeyseg parameter is specified, then the numseg parameter must be 1. The fields in rtr_keyseg_type_t that are used are:


ks_type          rtr_keyseg_foreign_tm_id 
ks_length        TM identifier. The TM identifier is the 
                 value extracted from the 2 least significant 
                 bytes of ks_length. (The other 2 bytes are 
                 ignored.) 


If numseg is zero or RTR_NO_NUMSEG, or numseg is 1 and pkeyseg is RTR_NO_PKEYSEG, then the transaction manager identifier (as stored in the journal) defaults to rtr_default_foreign_tm_id .

Client applications using nested transactions should specify a transaction manager identifier, particularly if more than one process opens RTR client channels using the same foreign transaction manager on one node, or if different types of foreign transaction managers are used on the same node.

When a process that has open foreign transaction manager client channels fails, then the foreign transaction manager must be able to find out from RTR what state the transactions are in that were active in that process. Thus the foreign transaction manager must be able to identify itself to RTR so that RTR can find out what transactions were active for that channel. Generally, foreign transaction manager client channels opened in the same process (and for the same manager) can have a common transaction manager identifier, but foreign transaction manager client channels opened in separate processes should have different transaction manager identifiers.


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 multi-threaded server application is strongly recommended for better throughput.
Return Value A value indicating the status of the routine. Possible status values are:
RTR_STS_DUPLRMNAME Duplicate rm partition name
RTR_STS_DTXOPENFAIL Distributed transaction request to open a session to the RM has failed
RTR_STS_INVFLAGS Invalid flags argument
RTR_STS_INVCHANNEL Invalid pchannel argument
RTR_STS_INVFACNAM Invalid FACNAM argument
RTR_STS_INVRCPNAM Invalid rcpnam argument
RTR_STS_INVEVTNUM Invalid evtnum argument
RTR_STS_INVACCESS Invalid access argument
RTR_STS_INVNUMSEG Invalid numseg argument
RTR_STS_INVPKEYSEG Invalid pkeyseg argument
RTR_STS_INVKSTYPE Invalid ks_type argument
RTR_STS_INVKSLENGTH Invalid ks_length argument
RTR_STS_INVRMNAME Invalid resource manager name
RTR_STS_INSVIRMEM Insufficient virtual memory
RTR_STS_OK Normal successful completion
RTR_STS_JOUNOTFOU Journal not found

An attempt was made to open a channel for use by a foreign transaction manager, but no RTR journal was found on this node.

RTR_STS_NOACP No RTRACP process available
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 
 * which 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, 
                    NULL, 
                    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 which 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 which 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 which 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, 
                  NULL, 
                  1, 
                  p_keyseg); 
check_status(status); 

For Use with XA

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

Example 3-3 Sample XA Server Application

 
void main( int argc, char *argv[] ) 
{ 
     server_key[0].ks_type = rtr_keyseg_unsigned; 
     server_key[0].ks_length = sizeof(rtr_uns_8_t); 
     server_key[0].ks_offset = 0; 
     server_key[0].ks_lo_bound = &low; 
 
server_key[0].ks_hi_bound = &high; 
     server_key[1].ks_type = rtr_keyseg_rmname;/* RM in use */ 
     server_key[1].ks_length = 0;              /* not applicable */ 
     server_key[1].ks_offset = 0; 
     server_key[1].ks_lo_bound = rm_name;      /* RM name */ 
     server_key[1].ks_hi_bound = xa_open_string; 
                                   /* RM open string */ 
 
 flag = RTR_F_OPE_SERVER | 
             RTR_F_OPE_NOSTANDBY | 
             RTR_F_OPE_XA_MANAGED |              /* XA flag */ 
             RTR_F_OPE_EXPLICIT_PREPARE | 
             RTR_F_OPE_EXPLICIT_ACCEPT; 
     rtr_open_channel(&server_channel, flag, fac_name, 
        NULL, RTR_NO_PEVTNUM, NULL, 2, server_key); 
        ... 
     rtr_receive_message(&server_channel, 
            RTR_NO_FLAGS,RTR_ANYCHAN, 
         &receive_msg,sizeof(receive_msg), 
            RTR_NO_TIMOUTMS, &msgsb); 
        ... 
     do 
     { 
        rtr_receive_message(&server_channel, RTR_NO_FLAGS,     RTR_ANYCHAN, 
           &receive_msg, sizeof(receive_msg),    RTR_NO_TIMOUTMS, &msgsb); 
 
 
         ... 
        msg = receive_msg.receive_data_msg; 
        switch(msgsb.msgtype) 
        { 
 
           case rtr_mt_msg1: 
           case rtr_mt_msgn: 
 switch(msg.txn_type) 
              { 
            case ... 
                    EXEC SQL ... 
              } 
              ... 
              rtr_reply_to_client(server_channel, RTR_NO_FLAGS, 
                 &reply_msg, sizeof(reply_msg), RTR_NO_MSGFMT); 
                 ... 
            case rtr_mt_prepare: 
                 ... 
              rtr_accept_tx(s_chan,RTR_NO_FLAGS,RTR_NO_REASON); 
                 ... 
            case rtr_mt_accepted: 
                  /* EXEC SQL COMMIT;   Comment out SQL Commits */ 
 
            case rtr_mt_accepted: 
                 /* EXEC SQL ROLLBACK;  Comment out SQL rollbacks */ 
 
              /* 
            case rtr_mt_msg1_uncertain: 
                 ... 
              */ 
                 ... 
        } 
            } while(...) 
 
            EXEC SQL COMMIT WORK RELEASE; 
            exit(0); 
       } 
 

Example 3-4 Use of Partition Names

/*  **  topen_channel.com  
 **  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_prepare_tx

Send a transactional message to a server, in the context of nested transactions.

Syntax

status = rtr_prepare_tx (channel, flags, reason, pmsg, msglen)

Argument Data Type Access
status rtr_status_t write
channel rtr_channel_t read
flags rtr_pre_flag_t read
reason rtr_reason_t read
pmsg rtr_msgbuf_t read
msglen rtr_msglen_t read


C Binding

rtr_status_t rtr_prepare_tx (


rtr_channel_t channel ,
rtr_pre_flag_t flags ,
rtr_reason_t reason ,
rtr_msgbuf_t pmsg ,
rtr_msglen_t msglen ,
)


Arguments

channel

The channel identifier (returned earlier by the rtr_open_channel() call).

flags

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

reason

Optional reason for preparing the transaction. The reason is ORed with the reasons of the other participants in the transaction and returned in the reason field of the rtr_status_data_t structure returned with the rtr_mt_prepared message to all participants in the transaction. Specify RTR_NO_REASON if no reason is required.

pmsg

Pointer to the message to be sent.

msglen

Length in bytes of the message to be sent, up to RTR_MAX_BLOB_LEN bytes. The value of RTR_MAX_BLOB_LEN is defined as 2048 in rtr.h.

Description

The rtr_prepare_tx() call can only be used in the context of nested transactions (that is, rtr_start_tx() was called with the parameter jointxid not equal to RTR_NO_JOINTXID). If this call returns RTR_STS_OK, then the first (prepare) phase of the RTR two-phase commit protocol has been initiated.

A new message type is associated with this call, rtr_mt_prepared. Like the message types rtr_mt_accepted and rtr_mt_rejected, the rtr_mt_prepared message type returns data of type rtr_status_data_t in the user buffer. In this case, the status field of rtr_status_data_t is always RTR_STS_OK, and the reason field contains the same reason mask that would be returned in the rtr_mt_accepted message type for the same transaction were the transaction to be accepted. For an example of use of the reason mask, see the RTR Application Design Guide.

Only when the rtr_mt_prepared message is delivered, can the application be sure that all participants of the nested transaction are ready to commit. Alternatively, calling rtr_prepare_tx() can cause delivery of the message rtr_mt_rejected, if one of the participating servers votes to reject the nested transaction.

The rtr_mt_prepared message is only delivered to the application if the rtr_prepare_tx is called.

A call to rtr_prepare_tx must be followed by a call to rtr_accept_tx (or rtr_reject_tx), which in this context implements the commit phase of the two-phase commit. (Generally, rtr_prepare_tx and rtr_accept_tx will be called by the foreign transaction manager directly, not by the application.)

The reason parameter to rtr_prepare_tx is used in place of the reason parameter in the subsequent rtr_accept_tx call (that is, the reason field in the call to rtr_accept_tx or rtr_reject_tx which follows a call to rtr_prepare_tx is ignored).

The pmsg parameter can be used to pass a block of data to RTR that will be saved in the local journal. This data is not sent to the router or backends, and is used only during recovery, when it is passed back to the client application. RTR does not interpret or modify this data in any way.

The maximum size of data that can be passed in a prepare call is defined as RTR_MAX_BLOB_LEN.

Return Value A value indicating the status of the routine. Possible status values are:
RTR_STS_OK Normal successful completion
RTR_STS_INVCHANNEL Invalid channel argument
RTR_STS_INVFLAGS Invalid flags argument
RTR_STS_INVMSGLEN Invalid msglen argument
The size of data in pmsg cannot be larger than RTR_MAX_BLOB_LEN .
RTR_STS_INSVIRMEM Insufficient virtual memory
RTR_STS_NOTNESTEDTX TX in progress is not nested
The transaction in progress on this channel is not a nested transaction.

Example


rtr_string_t prep_msg = 
"Preparing create_new_member transaction"; 
/* 
 * The transaction was explicitly started, and multiple 
 * messages sent. It is now time to commit the full 
 * transaction. The client notifies RTR and the server 
 * to prepare the transaction; this is the first phase of 
 * RTR's two-phase commit protocol. 
 */ 
        status = rtr_prepare_tx( 
                &channel, 
                RTR_NO_FLAGS, 
                RTR_NO_REASON, 
                prep_msg,               
        // Write this message to journal. 
                strlen(prep_msg)); 
 
        check_status(status); 
 
/* The client should now expect to receive an rtr_mt_prepared 
 * message from the server in a future rtr_receive_message call, 
 * indicating that all participants are prepared, and ready to 
 * commit the transaction. 
 */ 
status = rtr_receive_message( 
                        &channel, 
                        RTR_NO_FLAGS, 
                        RTR_ANYCHAN, 
                        &receive_msg, 
                        sizeof(receive_msg), 
                        receive_time_out, 
                        &msgsb); 
 
        check_status( status ); 
 
        if (rtr_msg_type_t == rtr_mt_prepared) 
        { 
                status = rtr_accept_tx( 
                            &channel, 
                            RTR_NO_FLAGS, 
                            RTR_NO_REASON ); 
                check_status( status ); 
        } 
else 
        // Issue an error; possibly retry. 

See Also


Previous Next Contents Index