PV-WAVE Foundation > Application Developer Guide > Interapplication Communication for UNIX > Communication with Remote Procedure Calls (UNIX Only)
Communication with Remote Procedure Calls (UNIX Only)
PV‑WAVE can communicate with user-written applications by establishing a client/server relationship based upon Sun Remote Procedure Call (RPC) technology. PV‑WAVE is able to act as either the client or server depending upon the requirements of the particular user-written application. This means that the user-written application can also act as either the client or server.
Remote Procedure Call (RPC) Technology
Remote procedure calls are a high-level communications paradigm which allow distributed applications to be developed using procedure calls which shield the programmer from knowing the details of the underlying network mechanisms. RPC implements a client-to-server communications system designed to support interapplication communication over a network. Data for RPC calls is transmitted using the External Data Representation (XDR) Standard.
PV‑WAVE uses RPC calls to transmit data in XDR format between hosts across the network or between processes on the same host. The parameters used with the functions CALL_UNIX or CALL_WAVE (described later in this section) are “packed” into a proprietary variable structure, transmitted in an XDR format and then “unpacked” and made available for PV‑WAVE and/or the user’s application.
For the purpose of our discussion, the following terms and definitions are used. A client initiates the remote procedure calls to a server. A server provides network access to a collection of one or more remote applications. A server may support multiple remote applications or multiple versions of the same remote application.
A client initiates the interapplication communication by sending a procedure call message to the server process and then waits (blocks) for a procedure reply message. The procedure call message contains the remote application’s parameters, among other things. The procedure reply message contains the results from the remote application, among other things. Once the client has received the results through the procedure reply message, the results are made available to the client and program execution continues.
On the server side, the process is dormant while it awaits the arrival of a procedure call message. When this message arrives, the server process extracts the parameters passed from the client and passes them to the remote application. The remote application performs its tasks with the supplied parameters and returns the results to the server process. The server then sends a procedure reply message to the client and returns to a dormant state awaiting the next procedure call message from a client.
Synchronization of Client and Server Processes
Because client and server processes can be started and run independently of one another, it is possible for the client and server processes to be out of synchronization. In general, especially on relatively unloaded systems, synchronization is not a problem. However, it is good practice to ensure that the server process is in a state that can handle client requests before the client process is started.
If PV‑WAVE is the server process, then it should be in a state to begin receiving client requests after the following message appears (assuming that the !Quiet system variable is zero):
Compiled - UNIX_LISTEN
If an external program that you wrote is used as the server process, you might want to include code in the program that lets PV‑WAVE clients know when it is appropriate to begin RPC transactions.
Another alternative is simply to wait for a period of time before starting the client process; however, the amount of time required will vary greatly depending on the load of the client system and the load of the server system, which in some cases may be the same system.
Using PV-WAVE as a Client: CALL_UNIX
CALL_UNIX is designed to allow users to access applications on the same host machine running PV‑WAVE or across a network to a remote host.
The usage for CALL_UNIX is:
CALL_UNIX(param [, ...])
where param is a variable parameter of any PV‑WAVE type.
For a complete description of CALL_UNIX, see the PV‑WAVE Reference.
In most cases where PV‑WAVE is the client, a user desires to send data from PV‑WAVE to an existing application to perform specific tasks and return the result to PV‑WAVE for further analysis. In any case, the user must write a server process which acts as an interface between PV‑WAVE and his or her application. Figure 2-2: Interapplication Communication: PV-WAVE as Client shows schematically how PV‑WAVE is used as a client.
 
Figure 2-2: Interapplication Communication: PV-WAVE as Client
When using PV‑WAVE as a client, users must first write a server to interface between PV‑WAVE and their application. The server makes a call to the PV‑WAVE RPC interface module w_listen, which is discussed in the section "Description of C Functions Used with CALL_UNIX". When the server is started in the background, w_listen “sits and waits” for a procedure call message from PV‑WAVE with the appropriate program number.
Once the server has been placed in this state, PV‑WAVE as the client initiates the interapplication communication by calling CALL_UNIX with the necessary parameters and keywords. CALL_UNIX opens a socket for communication, packs the parameters into XDR format and then transfers the data to the server. The data is then “unpacked” by using w_get_par, which is discussed in the section "Description of C Functions Used with CALL_UNIX".
It is essential that argument parameters passed to the server be in the proper order and be of the expected type and structure. The type, number and structure of parameters can be checked within a PV‑WAVE procedure before the call to the server is made. The unpacked parameters can then be used in a call to the remote application.
After execution of the remote application is complete, the results are passed back to PV‑WAVE using one of the following three routines:
w_smpl_reply—Use this C routine when no passed parameters have been modified and there is only a single return value/array.
w_send_reply—Use this C routine if the input parameters have been modified and must be sent back to PV‑WAVE in addition to some return value/array.
w_cmpnd_reply—Use this C routine to return multi-dimensional arrays.
Once the results have been returned to PV‑WAVE, program control returns to PV‑WAVE. The server can either exit or enter a new wait state.
Description of C Functions Used with CALL_UNIX
As explained previously, the CALL_UNIX function allows PV‑WAVE to communicate with a user-written application. CALL_UNIX sends parameters to a server process which then calls the user-written application.
The server uses the following C routines, which are discussed in detail later in this section:
*w_listen—Connect with the process running PV‑WAVE.
*w_get_par—Get the parameters.
*w_send_reply, w_smpl_reply, or w_cmpnd_reply—Send values and parameters back to PV‑WAVE.
*If an error occurs in a call to CALL_UNIX, it returns –1. The function ON_IOERROR can also be used to catch CALL_UNIX errors.
w_listen
When placed in an external C source file, allows the routine to “sit and wait” until it is called.
Usage
int w_listen (int program_number, char **user, char **procedure)
Discussion
When w_listen exits, the values of the parameters user, and procedure have been set. Use these strings in the external routine to control access to, and program flow in, the external routine.
Returned Value
w_listen returns a status of –1 if an error occurs, 1 otherwise.
Input Parameters
program_number—A unique identifier, set within the external routine that enables w_listen to determine which calls from CALL_UNIX are intended for this particular server. If the value of program_number is the same as the value of program_number in another server, the communication with the first server will be lost. If communication with a server is lost, use the kill -9 command.
user—A pointer to a string pointer. The parameter user is set by the keyword User in the CALL_UNIX call and set by w_listen. The intended use of user is to control access to the external routine. The memory that holds the string has already been allocated.
procedure—A pointer to a string pointer. The parameter procedure is set by the keyword Procedure in the CALL_UNIX call. The intended use of procedure is to control program flow in the external routine. The memory that holds the string has already been allocated.
w_get_par
Returns a specified parameter passed by CALL_UNIX.
Usage
char *w_get_par (int param_number, type);
Parameters
param_number—The index of the list of parameters. param_number is zero-based, so a value of zero will cause w_get_par to return a pointer to the first parameter, a value of one will cause w_get_par to return a pointer to the second parameter and so on.
type—The type of variable to be retrieved.
Discussion
Because of the way that functions are declared in C, w_get_par returns a pointer to a char, which is then cast to a pointer to the type of parameter desired. The space pointed to by the return value is allocated and freed by the RPC software. When the external routine replies to the client, the allocated space is freed. Thus, if there is a need to save a value returned by w_get_par, the value pointed to by the return value of w_get_par must be copied into a variable. w_get_par returns NULL if there is no such parameter or the specified parameter is not of the specified type.
The types are defined in the file $WAVE_DIR/src/rpc/wave_rpc_extern.h. For example, TYP_LONG will cause w_get_par to return a pointer to a long. To specify an array, perform a bitwise OR of the type of the array with the constant TYP_ARRAY. For example, if the third parameter passed from CALL_UNIX to the server is an array of long, you would use the following code to get the array:
long *ex_long_array;
ex_long_array = (long *) w_get_par (2, TYP_LONG | TYP_ARRAY);
After the external routine has completed its processing, it will need to return information to the client. Three routines are supplied that are used to return the information. All three of these routines return a status value of –1 to indicate an error and 0 to indicate success.
 
note
When one of these three routines is called, all the memory that the parameters occupied in the RPC software is freed. In the preceding example, the array that example_long_array points to will be freed.
w_smpl_reply and w_send_reply
*w_smpl_reply—Sends a single value array as the return value of CALL_UNIX.
*w_send_reply—Is used when it is necessary to modify and return parameters that have been passed in from CALL_UNIX.
Usage
int w_simpl_reply (type, long number_of_items, char *items);
int w_send_reply (type, long number_of_items, char *items);
Parameters
type—The type of variable to be returned, as defined in the file:
$WAVE_DIR/src/rpc/wave_rpc_extern.h
To specify an array, perform a bitwise OR of the type of the array with the constant TYP_ARRAY.
number_of_items—The number of items to be returned by the server. If an array is being returned, number_of_items is the length of the array, otherwise, number_of_items is set to one.
items—A pointer to the item(s) being returned. w_smpl_reply and w_send_reply expect pointers to char, so they may have to be type cast.
Discussion
w_smpl_reply can be thought of as giving the CALL_UNIX function a call by value parameter-passing mechanism. Only scalar values or single-dimension arrays (vectors) or scalars can be returned by w_smpl_reply.
With w_send_reply, data passed to a server cannot “grow”. If the server was passed FLTARR(100), the remote application cannot “grow” this to FLTARR(1000) and return it. Thus, w_smpl_reply can be thought of as giving the CALL_UNIX function a call by reference parameter-passing mechanism. Only single-dimension arrays or scalars can be returned by w_send_reply.
w_cmpnd_reply
Passes a multi-dimensional array back from the server.
Usage
int w_cmpnd_reply (unsigned char reply_only, type, unsigned char number_dimensions, long dimensions[ ], char *items);
Parameters
reply_only—A flag that determines if the parameters sent by the client are modified and returned by the server. If reply_only has a value of one, then the parameters sent from the client are not returned by the server (call by value). Any other value of reply_only will cause the (possibly modified) parameters that were sent by the client to be sent by the server back to the client (call by reference).
typeThe type of variable to be returned. The types are defined in the file $WAVE_DIR/src/rpc/wave_rpc_extern.h. To specify an array, perform a bitwise OR of the type of the array with the constant TYP_ARRAY.
number_dimensions—The size of the dimensions array. The maximum value is eight.
dimensions—An array containing the sizes of the each of the array dimensions. To specify a 4 x 5 x 6 array, set number_dimensions to 3, and dimensions to [4,5,6].
items—A pointer to the item(s) being returned. w_cmpnd_reply expect pointers to char, so they may have to be type cast.
Example Server
An example server, rpc_wave_to_c, is provided online in the directory $WAVE_DIR/demo/interapp/rpc. The file rpc_wave_to_c contains three examples:
*Example_1—Accepts an array of long values. The array is passed to a function where each value is multiplied by two. The result is passed back and placed into the PV‑WAVE variable newarray.
newarray = CALL_UNIX(proc='example_l', 1000L, lindgen(1000))
print, newarray
*Example_2—Accepts a string and returns a string. An array of strings is passed to the server and then printed. A new string is returned and placed in the PV‑WAVE variable message.
strings=['one', 'two', 'three', 'four', 'five'] 
message=CALL_UNIX(proc='example_2', 5, strings)
print, message
*Example_3—Accepts a long array. This array is then filled by pseudo random numbers and returned. This example shows how to modify a passed parameter rather than always returning a result to a new variable. All parameters passed to the server in this example must be variables, otherwise, when the server attempts to modify a parameter, PV‑WAVE complains about not being able to store a value into a constant. old_array will contain an array of 1000 pseudo random numbers.
old_array=lonarr(1000) 
old_arr_len=l000L
new_len=CALL_UNIX(old_arr_len, old_array, proc='example_3')
print, new_len, old_array
Example Using CALL_UNIX
See the rpc_wave_to_c.pro example in $WAVE_DIR/demo/interapp/rpc.
Using PV-WAVE as a Server: CALL_WAVE
CALL_WAVE is designed to allow users to access PV‑WAVE from existing or planned applications on the same host machine running PV‑WAVE or across a network to a remote host. In most cases where PV‑WAVE is the server, the user desires to send data to PV‑WAVE either to access PV‑WAVE’s analytical routines or for plotting. In any case, the user must write a client process which acts as an interface between PV‑WAVE and his or her application. See Figure 2-3: Interapplication Communication: PV-WAVE as Server for an example of PV‑WAVE as a server.
To run PV‑WAVE as a server, start-up PV‑WAVE and run a procedure which calls UNIX_LISTEN.
 
PV‑WAVE is now in a “sit and wait” state. The user client application then initiates the interapplication communication by calling CALL_WAVE with the necessary parameters and keywords. CALL_WAVE opens a socket for communication, packs the arguments into XDR format and then transfers the data to PV‑WAVE.
UNIX_LISTEN receives this procedure call message, unpacks the data from the client and then makes it available to PV‑WAVE for some type of processing. UNIX_LISTEN can also return two strings to the PV‑WAVE environment. These strings can contain specific PV‑WAVE commands that specify the desired processing that should take place. Once this processing has been completed, PV‑WAVE returns the results to the client application through UNIX_REPLY. When the results have been returned, program control returns to the client while PV‑WAVE can either exit or enter a new wait state.
 
Figure 2-3: Interapplication Communication: PV-WAVE as Server
Description of C Functions Used with PV‑WAVE as Server
The function CALL_WAVE is a C function that can be used when PV‑WAVE is acting as a server..
CALL_WAVE
Calls a server and returns a pointer to a UT_VAR after the server has completed its task.
Usage
UT_VAR *CALL_WAVE(int argc, UT_VAR *argv[ ], char hostname [ ], int *unit, int close_unit, int program, char *procedure, char *user, int time_out)
Parameters
argc—The number of values in argv. argc is also the number of parameters that will be passed to PV‑WAVE.
argvAn array of pointers to UT_VAR. The UT_VARs contain the parameters that will be passed to PV‑WAVE. It is up to the application to load these structures properly.
hostnameThe name of the machine that the server (PV‑WAVE) is running on. hostname is necessary because there could be several servers, each with the same program number, but running on different machines.
unitA number that maps to an RPC socket. The purpose of unit is to allow the reuse of an open RPC socket, and thus avoid the overhead of re-opening the socket each time CALL_WAVE is called. However, based on experience, this overhead is not normally noticeable. If CALL_WAVE is called with NULL in the place of unit, no value is returned and a new socket is opened and closed after CALL_WAVE exits. If *unit is zero (i.e., unit == 0 and CALL_WAVE receives &unit), then a socket is opened and the socket number is returned in *unit. If *unit is greater than zero, socket number unit is used.
close_unitA flag telling CALL_WAVE to close unit after CALL_WAVE exits. If close_unit is non-zero, the unit is closed.
programA number identifying which server the application is calling. program is supplied in the C routine on the client. The value of program is the same value of the keyword Program in the UNIX_LISTEN call. If the UNIX_LISTEN call did not have the Program keyword in it, use zero for the value of program.
procedure—A string that is sent to the server. In the server, the UNIX_LISTEN keyword Procedure is used to retrieve the string. user is intended to be used for controlling program flow within the server.
userA string that is sent to the server. In the server, the UNIX_LISTEN keyword User is used to retrieve the string. procedure is intended to be used for controlling access to the routines within the server.
time_outThe time, in seconds, that CALL_WAVE will wait for PV‑WAVE to complete its task. There is no value for infinite time.
Discussion
The function CALL_WAVE calls a server and returns a pointer to a UT_VAR after the server has completed its task. UT_VAR is a structure for holding any valid type of PV‑WAVE variable. This UT_VAR pointer points to the value sent back in the reply parameter of UNIX_REPLY. Upon receiving a pointer to a UT_VAR, the application must determine the type of variable it references. The definitions of UT_VAR and other types can be found in the file:
$WAVE_DIR/src/rpc/wave_rpc_extern.h
For convenience, here is the definition of UT_VAR:
typedef struct
{
unsigned char type,
unsigned char element_size;
unsigned char n_dim,;
long dim[MAX_ARRAY_DIM];
UT_TYPES value;
} UT_VAR;
PV‑WAVE Functions Used with PV‑WAVE as Server
The UNIX_LISTEN and UNIX_REPLY functions are used when PV‑WAVE is acting as a server.
UNIX_LISTEN
The UNIX_LISTEN function allows external C routines to call PV‑WAVE. UNIX_LISTEN waits until a routine calls the function CALL_WAVE, and then returns the number of parameters with which it was called.
Parameters are accessed in the common block UT_COMMON, which is included in the server routine with the command @UT_COMMON. The first parameter is ut_param0, the second is ut_param1, and the thirtieth parameter is ut_param29. As well as being returned, the number of parameters is also contained in the variable ut_num_params in the UT_COMMON block.
For more detailed information on UNIX_LISTEN and its keywords, see the PV‑WAVE Reference.
UNIX_REPLY
When PV‑WAVE completes its processing and is ready to return information to the client, the function UNIX_REPLY is called. UNIX_REPLY has one parameter, reply, which is a variable that is sent back to the client. The CALL_WAVE function returns a pointer to a UT_VAR variable with the value of reply to the client. A keyword, Return_Params, is used if the server must modify the incoming parameters and return them. The number of parameters that is sent back is the same as the number that came in. This number is tracked internally by PV‑WAVE.
For more detailed information on UNIX_REPLY and its keywords, see the PV‑WAVE Reference.
Examples Using PV-WAVE as a Server
See the rpc_c_to_wave.c example in $WAVE_DIR/demo/interapp/rpc.