PicLan-IP RPC Services

March 8, 2001 - Preliminary Documentation

Overview of Remote Proceedure Calls

The purpose of remote proceedure calls is to provide a mechanism where application software running on one host system can call application software on a remote system bi-directionally passing parameters. With MultiValue DBMS systems this is implemented as the ability for an mv/BASIC application to call an mv/BASIC external subroutine remotely.

Once RPC services are available, the application program can implement nearly any needed functionality including remote file access and update, remote report execution, etc. In addition, because the connection occurs at an application program level, you can easily optimize your proceedure calls to maximize performance.

How are RPC Services licensed

The initial test release of RPC services use existing HTTP server and HTTP client PicLan-IP services. The next release (which should only be a couple of weeks away) will license RPC services seperately and at a lower cost. The end-user price list for RPC services is:

 
First 2 host systems $1500
Each additional host $500

All RPC licenses are bidirectional (or n-directional with more than 2 hosts) so that any system can call subroutines on any other system.

What are included with RPC Services

PicLan-IP RPC Services include the following features:

A future version of RPC Services will add the following features

Setting up a server to accept RPC requests

An RPC server is a computer system running PicLan-IP that can accept inbound requests.

Setting up the PICLAN-IP account

The PicLan-IP server will call your defined subroutines from the PICLAN-IP account. You must compile and catalog your subroutines so that they follow these guidelines:

Setting up the PICLAN-IP server

This proceedure wil change in a future release of PicLan-IP RPC support

In the PLIP.CTRL CONFIG file add the following line to the HTTP DIR lines:

HTTP DIR=*:80 /RPC/ FILE PLIP.RPC,PAGES

If your server runs on another IP address or port number, then you can include these in this line instead of "*:80".

If your server is multi-homed, you can include this line multiple time for different IP listen addresses or TCP port numbers.

The RPC functions will not interfere with other Coyote HTTP functions (assuming that you are not currently using a web directory named /rpc).

Creating a subroutine definition record

Before you can call a subroutine, you need to define a subroutine control record. This record is stored in the file PLIP.RPC,SUB. It has the following layout

 
ID The cataloged name of the subroutine that you are calling
001 The number of parameters in the subroutines parameter list
002 An optional password that controls access to the subroutine

Setting up a client to make RPC requests

Setting up your user account

This proceedure is still being designed. Suffice it to say that you will need many md items for this.

Creating a callable subroutine

PicLan-IP allows you to build a small local subroutine that has the same interface as the remote subroutine that you are calling. This allows you to write application code that appears to be completely local, even though remote proceedure calls are involved.

Building this local subroutine involves:

Defining a server system

Before you can call a server, you need to define a host system in the PLIP.RPC,SERVERS file. This file has the following layout

 
ID The name for the server that you are calling. If the server is located behind a "name based virtual host proxy server" then this name needs to be the actual domain name for the server that you are calling. Otherwise, you can use whatever local naming convention that you wish.
001 A multi-valued list of IP address/port numbers in the form 10.1.1.1:80. If your host is multi-homed, then you can include a multi-valued list of server addresses as in 10.1.1.1:80]10.1.3.1:80.
002 A DES1 or DES3 key to encrypt data send to the server (not currently implemented)
003 0 to 1 to indicate that the connection is to be compressed
004
005 The maximum number of seconds to wait for an outbound TCP connect or for TCP data to be transmitted (default 120)
006 The maximum number of bytes allowed in an outbound RPC transaction (default 1000000)
007 The maximum number of seconds to wait for an inbound TCP reply (default 120)
008 The maximum number of bytes allowed in an inbound RPC transaction (default 1000000)
009 The number of retries

Actually calling the remote subroutine

You can call the remote subroutine from your application by simply calling the subroutine that you built and compiled from the RPC template.

Tuning for Performance

There is not much to do in terms of tuning for performance except for paying attention to applicaton design.

Only pass the data that you need

If you are running on slow network connections, you should be careful to only pass the actual data needed. Extra data attributes require network transmission time. Also, flag parameters that only need to transfer in one direction as either In or Out instead of both.

On the other hand, if your network is fast, don't worry about this. The internal processing of RPC Services do not really mind large transactions (within reason) and it is only the network layer that is a concern. So, if you are using RPCs across a LAN, just throw the data around.

Minimize the number of transactions

The real area that you can optimize your application is by designing the RPC calls so that you need to make as few calls as practical. For example, if you need to read every item in a file, you should build an RPC that reads more than one item in a single call. Remember that a large part of the overhead of an RPC call is setting up the call, not transferring the data.

Programming tricks

Passing a variable number of dynamic arrays to a routine

One programming technique often needed is the ability to pass a variable number of parameters. With most data, you would just place this in a dynamic array. Things get more complicated if the data is itself a dynamic array. In this case, you can still pass the data in a single parameter using logic like:

Sending side:

DIM PARMS(500)



...


PARM = ''
FOR I = 1 TO 500
PARM<1,I> = LEN(PARMS(I)) NEXT I PARM = PARM : CHAR(254) FOR I = 1 TO 500 PARM = PARM : PARMS(I) NEXT I

Receiving side:

DIM PARMS(500)


...


T.CTRL = PARM<1>
T.DATA = PARM[LEN(T.CTRL)+2,999999999]

N = 1
FOR I = 1 TO 500
   PARM(I) = T.DATA[N,T.CTRL<1,I>]

   N = N + T.CTRL<1,I>
NEXT I