This topic includes the following sections:
This appendix contains a description of a one-client, one-server application called rpcsimp
that uses TxRPC. The source files for this interactive application are distributed with the Oracle Tuxedo ATMI software, except they are not included in the RTK binary delivery.
Before you can run this sample application, the Oracle Tuxedo software must be installed so that the files and commands referred to in this chapter are available.
rpcsimp
is a very basic Oracle Tuxedo ATMI application that uses TxRPC. It has one application client and one server. The client calls the remote procedure calls (operations) to_upper()
and to_lower()
, which are implemented in the server. The operation to_upper()
converts a string from lowercase to uppercase and returns it to the client, while to_lower()
converts a string from uppercase to lowercase and returns it to the client. When each procedure call returns, the client displays the string output on the user's screen.
What follows is a procedure to build and run the example.
Make a directory for rpcsimp
and cd
to it:
mkdir rpcsimpdir cd rpcsimpdir
Note: This is suggested so you will be able to see clearly therpcsimp files you have at the start and the additional files you create along the way. Use the standard shell (/bin/sh ) or the Korn shell; do not use the C shell (csh ). |
Set and export the necessary environment variables:
TUXDIR=<pathname of the Oracle Tuxedo System root directory> TUXCONFIG=<pathname of your present working directory>/TUXCONFIG PATH=$PATH:$TUXDIR/bin # SVR4, Unixware LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$TUXDIR/lib # HPUX SHLIB_PATH=$LD_LIBRARY_PATH:$TUXDIR/lib # RS6000 LIBPATH=$LD_LIBRARY_PATH:$TUXDIR/lib export TUXDIR TUXCONFIG PATH LD_LIBRARY_PATH SHLIB_PATH LIBPATH
Note: You needTUXDIR and PATH to be able to access files in the Oracle Tuxedo ATMI directory structure and to execute Oracle Tuxedo ATMI commands. You need to set TUXCONFIG to be able to load the configuration file. It may also be necessary to set an environment variable (for example, LD_LIBRARY_PATH ) if shared objects are being used. |
Copy the rpcsimp
files to the application directory:
cp $TUXDIR/apps/rpcsimp/* .
You will be editing some of the files and making them executable, so it is best to begin with a copy of the files rather than the originals delivered with the software.
List the files:
$ ls client.c rpcsimp.mk server.c simp.idl ubbconfig wclient.def wsimpdll.def $
Note: This list does not include files that are used in the DCE-Gateway example described in Appendix B, "A DCE-Gateway Application." |
The files that make up the application are described in the following sections.
Example A-1 simp.idl
[uuid(C996A680-9FC2-110F-9AEF-930269370000), version(1.0) ] interface changecase { /* change a string to upper case */ void to_upper([in, out, string] char *str); /* change a string to lower case */ void to_lower([in, out, string] char *str); }
This file defines a single interface, changecase
version 1.0, with two operations, to_upper
and to_lower
. Each of the operations takes a NULL-terminated character string, that is both an input and output parameter. Because no ACF file is provided, status variables are not used and the client program must be able to handle exceptions. Each operation has a void return indicating that no return value is generated. simp.idl
is used to generate the stub functions (see below).
Example A-2 client.c
#include <stdio.h> #include "simp.h" #include "atmi.h" main(argc, argv) int argc; char **argv; { idl_char str[100]; unsigned char error_text[100]; int status; if (argc > 1) {/* use command line argument if it exists */ (void) strncpy(str, argv[1], 100); str[99] = '\0'; } else (void) strcpy(str, "Hello, world"); TRY to_upper(str); (void) fprintf(stdout, "to_upper returns: %s\n", str); to_lower(str); (void) fprintf(stdout, "to_lower returns: %s\n", str); /* control flow continues after ENDTRY */ CATCH_ALL exc_report(THIS_CATCH); /* print to stderr */ (void) tpterm(); exit(1); ENDTRY (void) tpterm(); exit(0); }
The header, simp.h
, which is generated by the IDL compiler based on simp.idl
, has the function prototypes for the two operations. The simp.h
header also includes the header files for the RPC run-time functions (none appear in this example) and exception handling. The atmi.h
header file is included because tpterm(3c)
is called. If an argument is provided on the command line, then it is used for the conversion to uppercase and lowercase (the default being "hello world
"). Exception handling is used to catch any errors. For example, exceptions are generated for unavailable servers, memory allocation failures, communication failures, and so forth. The TRY
block encapsulates the two remote procedure calls. If an error occurs, the execution will jump to the CATCH_ALL
block which converts the exception (THIS_CATCH
) into a string, prints it to the standard error output using exc_report
, and exits. Note that in both the abnormal and normal execution, tidl(1)
is called to leave the application gracefully. If this is not done, a warning is printed in the userlog(3c)
for non-Workstation clients, and resources are tied up (until the connection times out, for Workstation clients).
Example A-3 server.c
#include <stdio.h> #include <ctype.h> #include "tx.h" #include "simp.h" int tpsvrinit(argc, argv) int argc; char **argv; { if (tx_open() != TX_OK) { (void) userlog("tx_open failed"); return(-1); } (void) userlog("tpsvrinit() succeeds."); return(1); } void to_upper(str) idl_char *str; { idl_char *p; for (p=str; *p != '\0'; p++) *p = toupper((int)*p); return; } void to_lower(str) idl_char *str; { idl_char *p; for (p=str; *p != '\0'; p++) *p = tolower((int)*p); return; }
As with client.c
, this file includes simp.h
.
It also includes tx.h
because tx_open(3c)
is called (as required by the X/OPEN TxRPC specification, even if no resource manager is accessed). A tpsvrinit(3c)
function is provided to ensure that tx_open()
is called once at boot time. On failure, -1
is returned and the server fails to boot. This is done automatically, so you may not need to supply it.
The two operation functions are provided to do the application work, in this case, converting to upper and lower case.
Example A-4 rpcsimp.mk
CC=cc CFLAGS= TIDL=$(TUXDIR)/bin/tidl LIBTRPC=-ltrpc all: client server # Tuxedo client client: simp.h simp_cstub.o CC=$(CC) CFLAGS=$(CFLAGS) $(TUXDIR)/bin/buildclient \ -oclient -fclient.c -fsimp_cstub.o -f$(LIBTRPC) # Tuxedo server server: simp.h simp_sstub.o CC=$(CC) CFLAGS=$(CFLAGS) $(TUXDIR)/bin/buildserver \ -oserver -s changecasev1_0 -fserver.c -fsimp_sstub.o \ -f$(LIBTRPC) simp_cstub.o simp_sstub.o simp.h: simp.idl $(TIDL) -cc_cmd "$(CC) $(CFLAGS) -c" simp.idl # # THIS PART OF THE FILE DEALING WITH THE DCE GATEWAY IS OMMITTED # # Cleanup clean:: rm -f *.o server $(ALL2) ULOG.* TUXCONFIG rm -f stderr stdout *stub.c *.h simpdce.idl gwinit.c clobber: clean
The makefile
builds the executable client and server programs.
The part of the makefile
dealing with the DCE Gateway (described in Appendix B, "A DCE-Gateway Application," is omitted from the figure.
The client is dependent on the simp.h
header file and the client stub object file. buildclient
is executed to create the output client executable, using the client.c
source file, the client stub object file, and the -ltrpc
RPC run-time library.
The server is dependent on the simp.h
header file and the server stub object file. buildserver
is an output server executable, using the server.c
source file, the server stub object file, and the -ltrpc
RPC run-time library.
The client and server stub object files and the simp.h
header file are all created by running the tidl
compiler on the IDL input file.
The clean
target removes any files that are created while building or running the application.
The following is a sample ASCII configuration file. The machine name, TUXCONFIG
, TUXDIR
, and APPDIR
must be set based on your configuration.
Example A-5 ubbconfig
*RESOURCES IPCKEY 187345 MODEL SHM MASTER SITE1 PERM 0660 *MACHINES <UNAME> LMID=SITE1 TUXCONFIG="<TUXCONFIG>" TUXDIR="<TUXDIR>" APPDIR="<APPDIR>" # MAXWSCLIENTS=10 *GROUPS GROUP1 LMID=SITE1 GRPNO=1 *SERVERS server SRVGRP=GROUP1 SRVID=1 #WSL SRVGRP=GROUP1 SRVID=2 RESTART=Y GRACE=0 # CLOPT="-A -- -n <address> -x 10 -m 1 -M 10 -d <device>" # # Tuxedo-to-DCE Gateway #simpgw SRVGRP=GROUP1 SRVID=2 *SERVICES *ROUTING
The lines for MAXWSCLIENTS
and WSL
would be uncommented and are used for a Workstation configuration. The literal netaddr
for the Workstation listener must be set as described in WSL(5)
in the Oracle Tuxedo File Formats and Data Descriptions Reference.
Edit the ASCII ubbconfig
configuration file to provide location-specific information (for example, your own directory pathnames and machine name), as described in the next step. The text to be replaced is enclosed in angle brackets. You need to substitute the full pathname for TUXDIR
, TUXCONFIG
, and APPDIR
, and the name of the machine on which you are running. The following is a summary of the required values.
TUXDIR
The full pathname of the root directory of the Oracle Tuxedo software, as set above.
TUXCONFIG
The full pathname of the binary configuration file, as set above.
APPDIR
The full pathname of the directory in which your application will run.
UNAME
The machine name of the machine on which your application will run; this is the output of the UNIX command uname -n
.
For a Workstation configuration, the MAXWSCLIENTS
and WSL
lines must be uncommented and the <address
> must be set for the Workstation Listener. (See WSL
(5) for further details.)
Build the client and server programs by running the following:
make -f rpcsimp.mk TUXDIR=$TUXDIR
Load the binary TUXCONFIG
configuration file by running the following:
tmloadcf -y ubbconfig
The native client program can be run by optionally specifying a string to be converted first to uppercase, and then to lowercase, as shown in the following:
$ client HeLlO to_upper returns: HELLO to_lower returns: hello $
When running on a Workstation, set the WSNADDR
environment variable to match the address specified for the WSL program. The Windows client can be run by executing:
>win wclient
Note: The dynamic link library may be used in a separately developed application such as a visual builder. |
You can monitor the RPC server using tmadmin
(1). In the following example, psr
and psc
are used to view the information for the server
program. Note that the length of the RPC service name causes it to be truncated in terse mode (indicated by the "+"); verbose mode can be used to get the full name.
Example A-6 tmadmin psr and psc Output
$ tmadmin > psr a.out Name Queue Name Grp Name ID RqDone Load Done Current Service ---------- ---------- -------- -- ------ --------- --------------- BBL 587345 SITE1 0 0 0 ( IDLE ) server 00001.00001 GROUP1 1 2 100 ( IDLE ) > psc Service Name Routine Name a.out Name Grp Name ID Machine # Done Status ------------ ------------ ---------- -------- -- ------- ------ ------ ADJUNCTBB ADJUNCTBB BBL SITE1 0 SITE1 0 AVAIL ADJUNCTADMIN ADJUNCTADMIN BBL SITE1 0 SITE1 0 AVAIL changecasev+ changecasev+ server GROUP1 1 SITE1 2 AVAIL > verbose Verbose now on. > psc -g GROUP1 Service Name: changecasev1_0 Service Type: USER Routine Name: changecasev1_0 a.out Name: /home/sdf/trpc/rpcsimp/server Queue Name: 00001.00001 Process ID: 8602, Machine ID: SITE1 Group ID: GROUP1, Server ID: 1 Current Load: 50 Current Priority: 50 Current Trantime: 30 Requests Done: 2 Current status: AVAILABLE > quit