This section shows a reliable RPC client for CLIENT_COMMIT
mode. All
methods for reliable RPC are defined in erx.h
. The methods
applicable to reliable RPC as described under
API Function Descriptions for Reliable RPC are:
ERXGetReliableState
ERXSetReliableState
ERXReliableCommit
ERXReliableRollback
ERXGetReliableID
ERXGetReliableStatus
Define the generated client header file. This header file includes the RPC runtime header file erx.h and defines structures and prototypes for your RPC messages.
/* include generated header file */ #include "cmail.h"
/* Required global variables for the CLIENT interface */ ERXeReturnCode ERXrc; ERX_CLIENT_IDENTIFICATION ERXClient; ERX_SERVER_ADDRESS ERXServer; ERX_SERVER_ADDRESS ERXServerDefault; ERXCallId ERXCallID; ERX_ERROR_INFO ERXErrorInfo;
For Implicit Logon, if required in your environment, the client password can be given here. It is provided then through the RPC interface object call.
/* set client identification */ memset( &ERXClient, 0, sizeof(ERXClient) ); ERXClient.pUserId = "ERX-USER"; ERXClient.pPassword = "ERX_PASS";
Your application will wait a maximum of 55 seconds for a server response. If the server does not answer within this period, the broker gives your program control again with an error code 00740074.
ERXServer.Medium = ERX_TM_BROKER_LIBRARY; ERXServer.ulTimeOut = 55; /* set Broker-Id, server-name, class-name and service-name */ strcpy( (char*) ERXServer.Address.BROKER.szEtbidName, "ETB001" ); strcpy( (char*) ERXServer.Address.BROKER.szServerName, "SRV1" ); strcpy( (char*) ERXServer.Address.BROKER.szClassName, "RPC" ); strcpy( (char*) ERXServer.Address.BROKER.szServiceName, "CALLNAT" );
As a general rule, you have to register the RPC runtime before you use it. After registration, the RPC runtime holds information on a per-thread basis. See also Using the RPC Runtime.
/* register to the RPC runtime */ ERXrc = ERXRegister(ERX_CURRENT_VERSION ); If ( ERX_FAILED( ERXrc ) ) { /* code for error handling */ }
We logon by EntireX Broker.
/* Logon to EntireX Broker Middleware */ ERXrc = ERXLogon( &ERXClient, ERXServer.Address.BROKER_Library.szEtbidName ); if(ERX_FAILED(ERXrc)) { /* code for error handling */ }
Before reliable RPC can be used, the reliable state must be set to
either ERX_RELIABLE_CLIENT_COMMIT
or ERX_RELIABLE_AUTO_COMMIT
.
/* Set reliable RPC state to client commit */ ERXrc = ERXSetReliableState(ERX_RELIABLE_CLIENT_COMMIT); if( ERX_FAILED(ERXrc) ) { /* code for error handling */ }
The RPC interface object SENDMAIL
is called as a C procedure. See Calling Servers as Procedures or Functions.
/* do the remote procedure call */ SENDMAIL( gTo, gSubject, gText);
Get the reliable RPC message ID before you commit any reliable RPC messages, otherwise the reliable ID will be lost and checking for the RPC message status will not be possible.
/* Get the reliable ID */ ERXrc = ERXGetReliableID( &ERXServer, pReliableID ); if( ERX_FAILED(ERXrc) ) { /* code for error handling */ }
After the reliable RPC message ID has been got, you can query the status
of the reliable RPC message. This is a separate call independent of any
reliable RPC messages, so we use the default server connection
(ERXServerDefault
). Valid reliable RPC message states can be found in header
file etbcdef.h. See Broker ACI Control Block Definition.
See Using Persistence and Units of Work, Understanding UOW Status and Broker UOW Status Transition in the platform-independent Administration documentation for more information.
/* Check the reliable RPC message status */ ERXrc = ERXGetReliableStatus( &ERXClient, &ERXServerDefault, pReliableID, pReliableStatus ); if( ERX_FAILED(ERXrc) ) { /* code for error handling */ }
Send a second reliable RPC message.
/* do the remote procedure call */ SENDMAIL( gTo, gSubject, gText);
Now we commit both reliable RPC messages. This will deliver all reliable RPC messages to the server if it is available.
/* Commit all made reliable RPC messages */ ERXrc = ERXReliableCommit( &ERXServer ); if( ERX_FAILED(ERXrc) ) { /* code for error handling */ }
For reliable RPC, the ERX_SERVER_ADDRESS
will be overwritten by the RPC
runtime, so it is necessary to reset the ERX_SERVER_ADDRESS
structure with the
required values.
/* * After an ERXReliableCommit we have to use a new server connection * so we restore our default server connection for further calls. */ memcpy(&ERXServer, &ERXServerDefault, sizeof(ERX_SERVER_ADDRESS));
To determine that reliable RPC messages are delivered, we query the reliable RPC message status again. See also Step 8 above.
Send a third reliable RPC message.
/* do the remote procedure call */ SENDMAIL( gTo, gSubject, gText);
Get the reliable RPC message ID. See also Step 7.
/* Get the reliable ID */ ERXrc = ERXGetReliableID( &ERXServer, pReliableID ); if( ERX_FAILED(ERXrc) ) { /* code for error handling */ }
After the reliable RPC message ID has been got, query the status of the reliable RPC message again.
/* Check the reliable RPC message status */ ERXrc = ERXGetReliableStatus( &ERXClient, &ERXServerDefault, pReliableID, pReliableStatus ); if( ERX_FAILED(ERXrc) ) { /* code for error handling */ }
Roll back the current reliable RPC message.
/* Roll back Message 3 */ ERXrc = ERXReliableRollback( &ERXServer ); if( ERX_FAILED(ERXrc) ) { /* code for error handling */ }
After rolling back the reliable RPC message, query the status of the reliable RPC message.
/* Get the reliable RPC message status */ ERXrc = ERXGetReliableStatus( &ERXClient, &ERXServerDefault, pReliableID, pReliableStatus ); if( ERX_FAILED(ERXrc) ) { /* code for error handling */ }
Log off from EntireX Broker.
/* Logoff from EntireX Broker Middleware */ ERXrc = ERXLogoff( &ERXClient, ERXServerDefault.Address.BROKER_Library.szEtbidName ); if ( ERX_FAILED( ERXrc ) ) { /* code for error handling */ }
As a general rule, after using the RPC runtime you should unregister from it. This will free all resources held by the RPC runtime for the caller. See Using the RPC Runtime for more information.
/* unregister to the RPC runtime */ ERXUnregister();
This section gives some hints for reliable RPC AUTO_COMMIT
mode. It is not
a complete example and shows only the correct order of reliable RPC method
calls. The reliable ID to check the message status must be retrieved
immediately after the reliable RPC message is sent and before any other RPC
runtime calls - otherwise the reliable ID is lost and retrieving the message
status is not possible.
/* Initialize pERXServer */ ... /* * After initializing pERXServer with your connection settings (broker ID, * server-name, class-name, service-name) create a copy of it * (pERXDefaultServer). Use this copy to resolve the reliable status after * a reliable RPC message. */ memcpy(pERXServer, pERXDefaultServer, sizeof(ERX_SERVER_ADDRESS)); ... /* Set reliable state to AUTO_COMMIT */ ERXSetReliableState( ERX_RELIABLE_AUTO_COMMIT ); ... /* reliable RPC message 1 */ SENDMAIL( gTo, gSubject, gText ); /* * The reliable ID must be resolved directly * after a reliable RPC message */ ERXGetReliableID( pERXServer, pReliableID ); ... /* Resolve the reliable status */ ERXGetReliableStatus( pERXClient, pERXDefaultServer, pReliableID, pReliableStatus ); ... /* For a second AUTO_COMMIT RPC message, use a new server connection */ memcpy(pERXServer, pERXDefaultServer, sizeof(ERX_SERVER_ADDRESS)); ... /* reliable RPC message 2 */ SENDMAIL( gTo, gSubject, gText ); /* * The reliable ID must be resolved directly * after a reliable RPC message */ ERXGetReliableID( pERXServer, pReliableID ); ... /* Resolve the reliable status */ ERXGetReliableStatus( pERXClient, pERXDefaultServer, pReliableID, pReliableStatus ); ...
There are no server-side methods for reliable RPC. The server does not send back a message to the client. The server can run deferred, thus client and server do not necessarily run at the same time. If the server fails, it returns an error code greater than zero. This causes the transaction (unit of work inside the Broker) to be cancelled, and the error code is written to the user status field of the unit of work.
For writing reliable RPC servers, see Using the C Wrapper for the Server Side (z/OS, UNIX, Windows, BS2000).
To execute a reliable RPC service with an RPC server, the parameter
logon
must be set to YES
, see
Configuring the RPC Server in the BS2000 Administration documentation or Configuring the RPC Server under Administering the RPC Server for C