This topic includes the following section:
The TxRPC feature allows programmers to use a remote procedure call (RPC) interface, such that a client process can call a remote function (that is, a remote service) in another process using a local function call. The application writer must specify the operations (that is, procedures) and data types that are used as parameters to those operations via an Interface Definition Language (IDL). Operations are grouped together in an interface. An IDL compiler is used to generate substitute procedures called stubs which allow the operation to be remote. An important concept to understand from the beginning is that there are two fundamental levels of naming: the interface has a name and within an interface, one or more operations are named. At run time, the interface is made available, which means that any of the operations in the interface can be called; an individual operation within an interface cannot be made available (if you need this, define the operation in its own interface).
The following illustrates how an RPC is made to look like a local procedure call.
The client application code calls one of the operations (functions) defined in the IDL file. Instead of calling the actual function, which resides on the server side, the client stub is called. The client stub is generated by the IDL compiler based on the IDL input file, which defines the data types and operations. For each operation, the input parameters, return type, and output parameters are defined. The client stub takes the input parameters and converts them into a single buffer of data, sends the data to the server and waits for a response, and unpacks the buffer of data sent back from the server (the return value and output parameters). The communication between the client and server processes, whether intra-machine or inter-machine is handled by the Oracle Tuxedo ATMI run time.
On the server side, the run time calls the server stub for the interface, also generated by the IDL compiler. This stub unpacks the data buffer that contains the input parameters, in some cases it allocates space needed for output parameters of the operation, calls the operation and waits for it to return, packs the return value and output parameters into a buffer and sends the response back to the client.
From the application perspective, it appears that a simple local procedure call is done. The stubs and the run time hide the calling of a remote procedure in a non-local address space (process).
The steps for building an application using remote procedure calls is very similar to building one without these calls. Most of the time will be spent writing the application code for the client and the server (where the real application work is done). The Oracle Tuxedo ATMI run time frees the application programmer from worrying about communications, translation of the data from the format used on the client machine to the format used on the server machine, and so forth. TxRPC may also be used to communicate between servers.
In addition to the steps needed for building a monolithic application, it is necessary to completely define the interface between the client and server. As stated earlier, the interface contains the definition of data types and operations used for the remote procedure calls. Normally, the name of the file containing the definition has an "
.idl" suffix; using this convention makes the file type self-documenting.
Every interface must have its own unique identifier. This Universal Unique Identifier (UUID) consists of 128-bits that uniquely identify the interface among all interfaces. The job of generating a UUID is done for the application programmer by the
uuidgen program. By running the
uuidgen program with the
-i option, it generates an interface template that contains a new UUID. Refer to Appendix A, "A Sample Application," for a complete example (including code) for the development of a simple RPC application; the first step illustrates how to run the
uuidgen command and the resulting output. More information about other options of this command are given in the
uuidgen(1) manual page.
The UUID is used at run time to ensure that the client stub matches the server stub on the receiving side. That is, the UUID is sent from the client to the server for validation by the Oracle Tuxedo ATMI run time, transparent to the application programmer.
Besides matching on the UUID, each interface also has a version number associated with it. The version consists of a major and minor number. If a version number is not specified as part of the interface definition, it defaults to 0.0. Thus, there may be multiple versions of the same interface available. The client requests a particular version of an interface by invoking the RPC in the stub generated from a particular interface version. Different versions imply that data types or operation parameters or returns have changed, or operations have been added to or deleted from the interface. Thus, the client and server UUID's and versions must match for a successful RPC. The application programmer must ensure that versions of the interface that have the same version numbers do provide the same (or a compatible) interface.
Once the template IDL is generated by
uuidgen, the application program must provide a definition of all data types and operations in the interface. The language looks very much like the declarative parts of C or C++ (without the procedural statements). Data types are declared via
typedef statements, and the operations are declared via function prototypes. Additional information is provided via IDL attributes. Attributes appear in the language within square brackets, for example, [in]. These provide information about such things as pointer types (for example, whether or not a pointer can be NULL at run time), about parameters (for example, whether a parameter is for input, output, or both), and much more. The IDL language and the associated compiler are discussed further in Chapter 2, "Using the Interface Definition Language (IDL)."
In addition to the IDL file, an optional Attribute Configuration File (ACF) may also be provided to give additional attributes of the interface. Most important is the definition of status variables in the operations for returning the status of each RPC operation. The use of status variables will be discussed further in Chapter 3, "Writing RPC Client and Server Programs." Attributes in the ACF file do not affect the communications between the client and server (as do attributes in the IDL file), but generally have an impact on the interface between the application code and the generated stubs.
When using the Oracle Tuxedo ATMI run time, the management of the binding (connection) between the client and server is done transparently. There is no information provided by the client or server application code to manage the client/server binding. (In contrast, when using the OSF DCE run time, considerable effort by the programmer must be given to binding management. Oracle Tuxedo ATMI runtime does not support the OSF DCE run time functions and ignores binding attributes in IDL and ACF files.)
The IDL and optional ACF files are compiled using the IDL compiler. The compiler first generates a header file that contains all of the type definitions and function prototypes for the operations defined in the IDL file. This header file can be included in application code that makes RPC calls defined in the interface. If the input files are
.acf, then the default header file name is
.h. The compiler generates stub code for both the client and server (for example,
_sstub.c). These stub files were described earlier and contain the data packaging and communications for the RPC. By default, the IDL compiler invokes the C compiler to generate client and server stub object files (for example,
_sstub.o) and the stub source files are removed. There are various IDL compiler options to request, limit generation of, and keep source and object files, and change the output filenames and directories. See the
tidl(1) reference page for further details.
After completing the interface definition, the major portion of work is writing the application code. The client code will call the operations defined in the interface, and the server code must implement the operations (note that a server can also act as a client by calling an RPC). Further considerations regarding writing the application are discussed in Chapter 2, "Using the Interface Definition Language (IDL)."
When the application code is completed, it's time to compile and link it together with the Oracle Tuxedo ATMI run time. Two programs are provided to simplify this process:
buildserver for the server, and
buildclient for the client. These programs compile any source files and link the object and library files with the Oracle Tuxedo ATMI run time to produce the executable files. These programs allow for alternate compilers and compilation options to be specified. See the
buildclient(1) reference pages for further details.
The complete process for building a server and client are shown in Figure 1-2 and Figure 1-3. More details about building client and server programs on different platforms are provided in Chapter 4, "Building RPC Client and Server Programs."
Figure 1-2 illustrates the following steps in the process for building a server:
uuidgen to generate a skeleton IDL file (
simp.idl) with a
UUID. Edit the template IDL file to define the interface between the client and server using the interface definition language.
Run the IDL compiler (
simp.idl and optional
simp.acf to generate the interface header file and the server stub object file.
After writing the server application code (
buildserver to compile it and link it with the server stub, Oracle Tuxedo ATMI run time, and TxRPC run time to generate an executable server.
The preceding figure illustrates the process for building a client.
Using the IDL file created in Step 1, run the IDL compiler (
tidl) to generate the interface header file and the client stub object file.
After writing the client application code (
buildclient to compile it and link it with the client stub, Oracle Tuxedo ATMI run time, and TxRPC run time to generate an executable client.
After building the application client and server, the application can be configured and booted, and the client run. This is discussed in Chapter 5, "Running the Application."