|
i |
|
This paper describes several enhancements to rpcgen designed
to facilitate the implementation of both traditional RPC programs
and also RPC programs with combinable RPC calls.
This proposal is based on RFCs 1831 and 1832 (RPC and XDR).
NFSv4 defines a new RPC interface with 38 procedure calls defined.
However, one is the NULL procedure and a second is the carrier
procedure for the remaining 36. That means that, as it stands,
the authors of the client and server procedures that support these
36 calls must manage the marshaling and unmarshaling of their
data into and out of the structures used by the carrier procedure.
This proposal augments the functionality of RPCGEN such that the
NFSv4 implementers, or the implementers of any other protocol so
conceived, shall not deal with such bookkeeping.
This proposal maintains binary compatibility with the proposed
NFSv4 standard. Any variations are bugs.
back to top
This all could have been written without
modifying the NFS4 XDR and, instead, just writing libraries specific
to the NFS4 and NFS4-CB programs. However, modifying RPCGEN was
rejected because it would have taken a lot of work and there is
already a tool that makes it relatively simple to do the text
expansions. With this tool and a small amount of added work, it has
been possible to generate the code to produce these
additional interfaces.
Terminology
The following terms are used throughout:
- carrier procedure
- This is a procedure that sends multiple queued procedure calls
at once. It is implemented with two calls. An "init" call
that will allocate data structures, and a "send" call to send the
queued calls and receive the multiple results.
- queued procedure calls
- These are procedure calls that are not sent immediately.
They are queued and sent when its carrier procedure's "send"
function is invoked.
- queued procedure callback
- When the carrier procedure receives its results, each of the
queued procedure calls had a callback procedure registered.
If the registered procedure address is not NULL, it will be
called with the complete argument list, input *and* output.
AutoXDR's Major functions
back to top
The implementation requires several changes to the way the
XDR data and RPC programs get defined. Principally, there are some
data that must be operated on by both the XDR compiler (rpcgen)
and by this new tool (AutoXDR). Rather than duplicate the information,
these common data are now expressed in a way that AutoGen can understand
and it will produce both the new files, and the traditional XDR file.
There are also a few additional bits of information that are needed by
AutoGen for the XDR templates, but not specifiable in the ONC IDL.
This is a summary of the changes. Greater detail on the requirements
for the AutoGen definitions file can be found in the example definitions file.
- Only one program may be defined at a time. If two different
programs have a lot of common data structures, then the common data can be
specified in a common definition file that is included by both of the
programs' AutoXDR definition files.
If you compile code that references both of these programs, you will need
to be careful and protect the data structures with something like:
#if defined( RPC_HDR )
%#ifndef HAVE_XDR_DATA_
%#define HAVE_XDR_DATA_
#elif defined( RPC_XDR )
%#ifndef HAVE_XDR_PROCS_
%#define HAVE_XDR_PROCS_
#endif
- The program specification must not
be supplied. Instead, you must use AutoGen definition syntax to
provide values for program, prog_id and one or
more copies of prog_version. You will find these
definitions very similar to the original definitions.
- The program must define the name of the status enumeration.
This is done by providing a definition for status_enum, such as:
status_enum = "nfs4_status";
- As with ONC's IDL, the procedures are defined as part of the compound
version (prog_version) definitions. Each defined procedure must have a p_name defined, and may have zero,
one or more arguments (p_arg) defined.
- Each argument must have an object type (def_type),
a name (def_name) and a usage (in, out or i_o attribute) defined. If the argument is normally
passed by value (a scalar), no passing type is specified. If the argument
is a fixed-length array, then it must have the array
attribute. Otherwise, the argument should be a structure that is passed by
reference and must have the ref attribute.
- Queued procedures are members of carrier procedure definitions.
They are defined as a p_op attribute(s) to the carrier
procedure. The arguments to a queueing procedure are specified exactly the
same way as the arguments to normal procedures, except they are each named
op_arg.
- Special enumerations (especially the error status enumeration)
can be specified in a way that will cause translation routines to be
emitted. Here is a trivial examle from NFSv4:
/*
* Error status
*/
enum = {
en_name = status;
en_ent[ 0] = { ename = OK;
etype = "successful completion"; };
en_ent[ 1] = { ename = PERM;
etype = "caller is either not privileged or not owner"; };
en_ent[ 2] = { ename = NOENT;
etype = "No such file or directory"; };
en_ent[ 256] = { ename = OMITTED;
etype = "operation omitted"; };
};
The enumeration for zero (0) is omitted.
- All other XDR data are passed through the AutoGen definitions
by setting one or more copies of xdr_data to the text to be
passed through.
back to top
Below are brief descriptions of the AutoXDR relevant files
and links to longer descriptions with brief examples.
The examples are based on a tiny fragment of the NFSv4 specification.
- Definitions
- A description of the AutoGen definitions that are used by AutoXDR. This
and the example test program below are the only files that are hand edited.
The remainder are generated for you.
- Client code
- This is the generated code that collects the arguments for the queued
procedures and marshals the arguments into and out of structures for the
clnt_call routine.
- Client header
- This is a generated file that declares the enumeration procedures
and, for queued procedures, the types of the queued procedure callbacks
and the procedure prototypes for the queueing procedures.
- Server code
- This is the generated code that handles the NULL procedure and the
servicing of the queued procedures. It will process the calls until a
threshold result code is exceeded. The default threshold is 0. This file is
not produced if there are no carrier procedures.
- Server header
- This is a generated file that declares the queued service routines that
the server side code will call. This file is not produced if there
are no carrier procedures.
- Enum translator
- This is the generated code that translates enumerations into strings
and back. It can be used on either the client or server side, but the
interface is declared in the client header.
- XDR IDL
- This is the ONC IDL or XDR file.
- Debug & Startup Code
- There are several debug and start up files that get generated.
The referenced page shows an example of the debug code only.
- *-debug.c
- This is a debug version substitution for the normal client code
(*-client.c). It will directly call the server code so that you can debug the
protocol in a single process. With this module, the XDR routines from rpcgen
and the server code, you have all the glue you
need to debug your RPC program inside of a single process.
- *-clmain.c
- This is a template file that can be used to start development of the
client. It includes code that will call every procedure once and, if there are
queued procedure calls, the callback procedures are generated and thecarrier
procedure's init and send procedures are called at the right
time. You should rename the file, if you choose to edit it. Otherwise,
it will be overwritten whenever these files are regenerated.
- *-svstub.c
- This file contains stub procedures for the server side. They will
all ignore their input arguments, print a message to stderr and return
success. Similar to the *-clmain.c file, you should rename this
file before editing it.
- Example Test
- If you compile this module and link it with the Debug Procedures, the Server code and the rpcgen-ed XDR module,
you will have a fully functional program that tests out this example
interface. e.g.:
$(CC) -o rpctest rpctest.o nfsv4-debug.o nfsv4-server.o nfsv4_xdr.o
|