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:
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,
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.
The rtr_open_channel() call opens a channel for communication with other applications on a particular facility.Return Value A value indicating the status of the routine. Possible status values are:The caller of rtr_open_channel() specifies the role (client or server) for which the channel is used.
- Change the rtr_open_channel() call as described in the call description.
- 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.
- RTR allows only one RM instance to be registered for each RTR partition.
- 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.
- Using a multi-threaded server application is strongly recommended for better throughput.
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 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 * 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);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_close_channel()
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.Return Value A value indicating the status of the routine. Possible status values are: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.
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
- rtr_receive_message()
- rtr_open_channel()
Previous Next Contents Index